mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
fix(Progress): fix render error when use v-show and improve performance
This commit is contained in:
parent
ce015ea1f4
commit
841e09d052
@ -1,15 +1,5 @@
|
|||||||
import {
|
import { computed, defineComponent, ExtractPropTypes } from 'vue';
|
||||||
ref,
|
|
||||||
watch,
|
|
||||||
computed,
|
|
||||||
nextTick,
|
|
||||||
reactive,
|
|
||||||
onMounted,
|
|
||||||
defineComponent,
|
|
||||||
ExtractPropTypes,
|
|
||||||
} from 'vue';
|
|
||||||
import { truthProp, createNamespace, addUnit } from '../utils';
|
import { truthProp, createNamespace, addUnit } from '../utils';
|
||||||
import { useExpose } from '../composables/use-expose';
|
|
||||||
|
|
||||||
const [name, bem] = createNamespace('progress');
|
const [name, bem] = createNamespace('progress');
|
||||||
|
|
||||||
@ -36,67 +26,56 @@ export default defineComponent({
|
|||||||
props,
|
props,
|
||||||
|
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const root = ref<HTMLElement>();
|
|
||||||
const pivotRef = ref<HTMLElement>();
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
rootWidth: 0,
|
|
||||||
pivotWidth: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const background = computed(() =>
|
const background = computed(() =>
|
||||||
props.inactive ? '#cacaca' : props.color
|
props.inactive ? '#cacaca' : props.color
|
||||||
);
|
);
|
||||||
|
|
||||||
const resize = () => {
|
const scaleX = computed(() => +props.percentage! / 100);
|
||||||
nextTick(() => {
|
const translateX = computed(() => {
|
||||||
state.rootWidth = root.value ? root.value.offsetWidth : 0;
|
let offset = 0;
|
||||||
state.pivotWidth = pivotRef.value ? pivotRef.value.offsetWidth : 0;
|
if (+props.percentage! !== 0) {
|
||||||
});
|
offset = (100 - +props.percentage!) / 2 / (+props.percentage! / 100);
|
||||||
};
|
}
|
||||||
|
return `${offset}%`;
|
||||||
|
});
|
||||||
|
|
||||||
const renderPivot = () => {
|
const renderPivot = () => {
|
||||||
const { rootWidth, pivotWidth } = state;
|
|
||||||
const { textColor, pivotText, pivotColor, percentage } = props;
|
const { textColor, pivotText, pivotColor, percentage } = props;
|
||||||
const text = pivotText ?? `${percentage}%`;
|
const text = pivotText ?? `${percentage}%`;
|
||||||
const show = props.showPivot && text;
|
const show = props.showPivot && text;
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
const left = ((rootWidth - pivotWidth) * +percentage!) / 100;
|
|
||||||
const style = {
|
const style = {
|
||||||
color: textColor,
|
color: textColor,
|
||||||
left: `${left}px`,
|
left: `${+percentage!}%`,
|
||||||
|
transform: `translate(-${+percentage!}%,-50%)`,
|
||||||
background: pivotColor || background.value,
|
background: pivotColor || background.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span ref={pivotRef} style={style} class={bem('pivot')}>
|
<span style={style} class={bem('pivot')}>
|
||||||
{text}
|
{text}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => [props.showPivot, props.pivotText], resize);
|
|
||||||
onMounted(resize);
|
|
||||||
useExpose({ resize });
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { trackColor, percentage, strokeWidth } = props;
|
const { trackColor, strokeWidth } = props;
|
||||||
const rootStyle = {
|
const rootStyle = {
|
||||||
background: trackColor,
|
background: trackColor,
|
||||||
height: addUnit(strokeWidth),
|
height: addUnit(strokeWidth),
|
||||||
};
|
};
|
||||||
const portionStyle = {
|
const portionStyle = {
|
||||||
background: background.value,
|
background: background.value,
|
||||||
width: (state.rootWidth * +percentage!) / 100 + 'px',
|
width: '100%',
|
||||||
|
transform: `scaleX(${scaleX.value}) translateX(-${translateX.value})`,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={root} class={bem()} style={rootStyle}>
|
<div class={bem()} style={rootStyle}>
|
||||||
<span class={bem('portion')} style={portionStyle}>
|
<span class={bem('portion')} style={portionStyle}></span>
|
||||||
{renderPivot()}
|
{renderPivot()}
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -108,30 +108,3 @@ progressRef.value?.resize();
|
|||||||
| --van-progress-pivot-font-size | _var(--van-font-size-xs)_ | - |
|
| --van-progress-pivot-font-size | _var(--van-font-size-xs)_ | - |
|
||||||
| --van-progress-pivot-line-height | _1.6_ | - |
|
| --van-progress-pivot-line-height | _1.6_ | - |
|
||||||
| --van-progress-pivot-background-color | _var(--van-primary-color)_ | - |
|
| --van-progress-pivot-background-color | _var(--van-primary-color)_ | - |
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### 组件从隐藏状态切换到显示状态时,渲染不正确?
|
|
||||||
|
|
||||||
Progress 组件在挂载时,会获取自身的宽度,并计算出进度条的样式。如果组件一开始处于隐藏状态,则获取到的宽度永远为 0,因此无法展示正确的进度。
|
|
||||||
|
|
||||||
#### 解决方法
|
|
||||||
|
|
||||||
方法一,如果是使用 `v-show` 来控制组件展示的,则替换为 `v-if` 即可解决此问题:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!-- Before -->
|
|
||||||
<van-progress v-show="show" />
|
|
||||||
<!-- After -->
|
|
||||||
<van-progress v-if="show" />
|
|
||||||
```
|
|
||||||
|
|
||||||
方法二,调用组件的 resize 方法来主动触发重绘:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<van-progress v-show="show" ref="progress" />
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
this.$refs.progress.resize();
|
|
||||||
```
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user