英文:
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.
<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>
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论