vue3[setup]父组件传递子组件数据同步更新四种方法以及性能分析

问题与原因

  • 问题: 本文章解决的问题是当父组件传递给子组件的值发生改变后,子组件不能立刻改变的问题。如下图代码所示,子组件的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

给子组件加上keykey的值为父组件传入子组件的值。

缺点: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
  • 理由:
  1. key会导致整个组件重新渲染,降低性能。
  2. computedwatch的代码更简洁清晰。
  3. computed内存有缓存机制(复用),效率更高,调试方便。

可使用watch监测值,在值改变时执行更多操作。


那么文章到这里就结束啦,祝大家好运常来

相关推荐
Small black human8 小时前
设计模式-应用分层
设计模式
速易达网络9 小时前
RuoYi、Vue CLI 和 uni-app 结合构建跨端全家桶方案
javascript·vue.js·低代码
lyj16899710 小时前
vue-i18n+vscode+vue 多语言使用
前端·vue.js·vscode
我在北京coding13 小时前
TypeError: Cannot read properties of undefined (reading ‘queryComponents‘)
前端·javascript·vue.js
海天胜景14 小时前
vue3 获取选中的el-table行数据
javascript·vue.js·elementui
翻滚吧键盘14 小时前
vue绑定一个返回对象的计算属性
前端·javascript·vue.js
乆夨(jiuze)15 小时前
记录H5内嵌到flutter App的一个问题,引发后面使用fastClick,引发后面input输入框单击无效问题。。。
前端·javascript·vue.js
小彭努力中15 小时前
141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
前端·javascript·vue.js·交互
xiguolangzi16 小时前
vue3+element-plus el-table列的显隐、列宽 持久化
前端·javascript·vue.js
码农秋16 小时前
设计模式系列(10):结构型模式 - 桥接模式(Bridge)
设计模式·桥接模式