重新渲染组件当初始渲染后 prop 值发生变化 (Vue 3)

huangapple go评论63阅读模式
英文:

Re-rendering a component when a prop value changes after initial render (Vue 3)

问题

嗨,

我正在尝试创建一个以特定方式行为的组件。

我想要发生的事情是,子组件应该最初使用给定的属性进行渲染,但当属性被更新(通过另一个组件发出值时),组件应该使用新的属性重新渲染。

目前,以下代码完成了我想要的一半。它未能在初始渲染时呈现传递给属性的内容,但成功地在通过更新的属性传递时重新呈现。

当我移除this.$watch函数时,我可以完成我想要的另一半,但似乎无法同时使两个所需的功能同时工作。

<template>
    <div class="progressDisplay">
        <div class="progressBar" ref="progressBar">
            <div class="coverCircle">
                <div class="valueContainer" ref="valueContainer"></div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        name: 'ProgressCircle',
        props: {
            endvalue: {
                type: Number,
                required: true
            }
        },
        data() {
            return {

            }
        },
        methods: {
            
        },
        computed: {

        },
        mounted() {
            this.$watch('endvalue', (newEndValue) => {
                let progressBar = this.$refs.progressBar;
                let valueContainer = this.$refs.valueContainer;

                let progressValue = 0;
                let speed = 10;

                let progress = setInterval(() => {
                    if (newEndValue < 0) {
                        valueContainer.innerText = '---';
                        clearInterval(progress);
                    } else {
                        if (this.newEndValue !== 0) {
                            progressValue++;
                        }
                        valueContainer.innerText = `${progressValue}%`;
                        if (progressValue >= 100) {
                            valueContainer.style.color = 'green';
                            progressBar.style.background = 'green';
                        } else {
                            valueContainer.style.color = 'black';
                            progressBar.style.background = `conic-gradient( 
                                #192A44 ${progressValue * 3.6}deg,
                                #EEEEEE ${progressValue * 3.6}deg
                                )`
                        }
                    }
                    if (progressValue === this.endvalue) {
                        clearInterval(progress);
                    }
                }, speed);
            })
        },
    }
</script>
<style scoped>
    .progressDisplay {
    display: flex;
    justify-content: center;
    align-self: center;
    height: 300px;
    width: 300px;
    }

    .progressBar {
    height: 250px;
    width: 250px;
    border-radius: 50%;
    background-color: #EEEEEE;
    display: grid;
    place-items: center;
    -webkit-box-shadow: inset -8px -2px 3x -1px rgba(0, 0, 0, 0.02);
    -moz-box-shadow: inset -8px -2px 3px -1px rgba(0,0,0,0.02);
    box-shadow: inset -8px -2px 3px -1px rgba(0, 0, 0, 0.068);
    }

    .coverCircle {
    height: 200px;
    width: 200px;
    display: grid;
    place-items: center;
    background-color: white;
    border-radius: 50%;
    -webkit-box-shadow: -8px -2px 43px -1px rgba(0,0,0,0.31);
    -moz-box-shadow: -8px -2px 43px -1px rgba(0,0,0,0.31);
    box-shadow: -8px -2px 2px -rgba(0, 0, 0, 0.077);
    }

    .valueContainer {
    position: relative;
    font-size: 34px;
    font-weight: 500;
    }
</style>

我不确定我所做的是否正确,或者我是否漏掉了什么。

英文:

Heyo,

I am trying to create a component that behaves in a particular way.

What I want to have happen is the child component to initially render with the prop it is given, but when the prop is updated (through another component emitting a value), the component should re-render with the new prop.

Currently, the following code accomplishes half of what I want. It fails to render what is passed into the prop the first time for the initial render but successfully re-renders when an updated prop is passed through.

I can accomplish the other half of what I want when I remove the this.$watch function, but I can't seem to get both pieces of desired functionality to work at the same time.

&lt;template&gt;
&lt;div class=&quot;progressDisplay&quot;&gt;
&lt;div class=&quot;progressBar&quot; ref=&quot;progressBar&quot;&gt;
&lt;div class=&quot;coverCircle&quot;&gt;
&lt;div class=&quot;valueContainer&quot; ref=&quot;valueContainer&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
export default {
name: &#39;ProgressCircle&#39;,
props: {
endvalue: {
type: Number,
required: true
}
},
data() {
return {
}
},
methods: {
},
computed: {
},
mounted() {
this.$watch( &#39;endvalue&#39;, ( newEndValue ) =&gt; {
let progressBar = this.$refs.progressBar;
let valueContainer = this.$refs.valueContainer;
let progressValue = 0;
let speed = 10;
let progress = setInterval(() =&gt; {
if ( newEndValue &lt; 0 ) {
valueContainer.innerText = &#39;---&#39;;
clearInterval( progress );
} else {
if ( this.newEndValue !== 0 ) {
progressValue++;
}
valueContainer.innerText = `${ progressValue }%`;
if ( progressValue &gt;= 100 ) {
valueContainer.style.color = &#39;green&#39;;
progressBar.style.background = &#39;green&#39;;
} else {
valueContainer.style.color = &#39;black&#39;;
progressBar.style.background = `conic-gradient( 
#192A44 ${ progressValue * 3.6}deg,
#EEEEEE ${ progressValue * 3.6}deg
)`
}
}
if ( progressValue === this.endvalue ) {
clearInterval( progress );
}
}, speed);
})
},
}
&lt;/script&gt;
&lt;style scoped&gt;
.progressDisplay {
display: flex;
justify-content: center;
align-self: center;
height: 300px;
width: 300px;
}
.progressBar {
height: 250px;
width: 250px;
border-radius: 50%;
background-color: #EEEEEE;
display: grid;
place-items: center;
-webkit-box-shadow: inset -8px -2px 3x -1px rgba(0, 0, 0, 0.02);
-moz-box-shadow: inset -8px -2px 3px -1px rgba(0,0,0,0.02);
box-shadow: inset -8px -2px 3px -1px rgba(0, 0, 0, 0.068);
}
.coverCircle {
height: 200px;
width: 200px;
display: grid;
place-items: center;
background-color: white;
border-radius: 50%;
-webkit-box-shadow: -8px -2px 43px -1px rgba(0,0,0,0.31);
-moz-box-shadow: -8px -2px 43px -1px rgba(0,0,0,0.31);
box-shadow: -8px -2px 2px -rgba(0, 0, 0, 0.077);
}
.valueContainer {
position: relative;
font-size: 34px;
font-weight: 500;
}
&lt;/style&gt;

I am not sure if there what I am doing is on the right path or if I am just missing something.

答案1

得分: 0

我最终只是使用了updated()生命周期钩子来在初始渲染后重新渲染这个组件。

不确定这是否是最优的方法,但它有效。

英文:

I ended up just using the updated() lifecycle hook to re-render this component after the initial render.

Not sure if this was the most optimal way to do this but it works

huangapple
  • 本文由 发表于 2023年6月19日 02:42:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502058.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定