问题与原因
- 问题: 本文章解决的问题是当父组件传递给子组件的值发生改变后,子组件不能立刻改变的问题。如下图代码所示,子组件的
loading
变量没有发生改变。
js
//父组件
<template>
<div class="page">
<loadingVue :process="load"/>
</div>
</template>
<script setup>
import { ref } from "vue";
import loadingVue from "../components/loading.vue";
let load = ref(0);
setInterval(() => {
if(load.value == 100){
load.value = 0;
}else{
load.value +=10;
}
}, 1000)
</script>
js
//子组件
<template>
<div class="load_component">
<div class="petal" v-for="index in sum" :style="`transform: rotate(${-60+index*360/sum}deg)`"></div>
<div class="flowerCore"></div>
<div class="loading_text">loading<span>...</span></div>
<div class="process_text"><div class="span">{{ loading }}</div> % </div>
</div>
</template>
<script setup name="loading">
import { computed, ref, watch } from "vue";
let sum = ref(6);
let props = defineProps(["process"]);
let loading = ref(props["process"]);
</script>
- 原因: 原因是接收父组件传递的值赋值在
props
变量里,而loading
变量拷贝了props["process"]
的值后,不会再关联props
的改变。
解决方法
直接使用props
既然父组件传递的值是由props
接收,那么直接使用props
变量就好了。
缺点:代码会很杂乱,容易堆史山。
- 修改后代码:
js
//子组件
<template>
<div class="load_component">
<div class="petal" v-for="index in sum" :style="`transform: rotate(${-60+index*360/sum}deg)`"></div>
<div class="flowerCore"></div>
<div class="loading_text">loading<span>...</span></div>
<div class="process_text"><div class="span">{{ props["process"] }}</div> % </div>
</div>
</template>
<script setup name="loading">
import { computed, ref, watch } from "vue";
let sum = ref(6);
let props = defineProps(["process"]);
使用key
给子组件加上key
,key
的值为父组件传入子组件的值。
缺点:1. 若父传子的值不止一个,那使用哪一个作为
key
呢?2. 每次改变都会重新渲染整个子组件,容易降低性能。
- 修改后代码:
js
//父组件
<template>
<div class="page">
<loadingVue :process="load" :key="load"/>
</div>
</template>
<script setup>
import { ref } from "vue";
import loadingVue from "../components/loading.vue";
let load = ref(0);
setInterval(() => {
if(load.value == 100){
load.value = 0;
}else{
load.value +=10;
}
}, 1000)
</script>
使用computed
给loading
变量使用computed
属性,同步computed["process"]
的变化。
- 修改后代码:
js
//子组件
<template>
<div class="load_component">
<div class="petal" v-for="index in sum" :style="`transform: rotate(${-60+index*360/sum}deg)`"></div>
<div class="flowerCore"></div>
<div class="loading_text">loading<span>...</span></div>
<div class="process_text"><div class="span">{{ loading }}</div> % </div>
</div>
</template>
<script setup name="loading">
import { computed, ref, watch } from "vue";
let sum = ref(6);
let props = defineProps(["process"]);
let loading = computed(()=>{
return props["process"]
})
使用watch
用watch
监测props["process"]
值的改变。
缺点:watch只是监听,监听后还需要更进一步的操作,不便捷、清晰。
- 修改后代码:
js
//子组件
<template>
<div class="load_component">
<div class="petal" v-for="index in sum" :style="`transform: rotate(${-60+index*360/sum}deg)`"></div>
<div class="flowerCore"></div>
<div class="loading_text">loading<span>...</span></div>
<div class="process_text"><div class="span">{{ loading }}</div> % </div>
</div>
</template>
<script setup name="loading">
import { computed, ref, watch } from "vue";
let sum = ref(6);
let props = defineProps(["process"]);
watch(()=>props["process"],(val,pre)=>{
loading.value = val;
})
性能分析
- 推荐:
computed
>watch
>key
- 理由:
key
会导致整个组件重新渲染,降低性能。computed
比watch
的代码更简洁清晰。computed
内存有缓存机制(复用),效率更高,调试方便。
可使用watch监测值,在值改变时执行更多操作。
那么文章到这里就结束啦,祝大家好运常来