vue子组件无法根据prop属性值变法实现视图更新问题记录
创始人
2025-05-29 20:44:46

问题描述

在vue中,有一个父组件和一个子组件,在父组件里有一个变量,在这个变量里有一个属性值和一个回调函数,并且这个变量是通过computed直接return的,如下:

computed: {testObj() {return {name: '空标题',cb(option) {option.name = '标题更改了'}}}
}

在这个父组件中调用子组件并通过prop的形式将这个对象传递给子组件,如下:


testChild 这个子组件中,展示这个变量的name值,并有一个事件会触发这个变量的回调函数,更改这个name值,如下:


export default {name: 'TestChild',props:{testObj: {type: Object,default: ()=>({})}},mathods: {updateTest() {this.testObj.cb(this.testObj)console.log(this.testObj)}}
}

现在的问题是,在子组件触发更新事件后,通过console打印可以看到testObj中的name值已经发生了改变,但是视图并没有更新

原因分析

子组件视图之所以没有根据响应式实现更新跟computed的实现原理有关,在vue中,可以通过datacomputedpropwatch的方式为当前实例中的变量添加上响应式(vue2通过defineProperty方法,vue3通过proxy,实现原理这里不赘述)。但是他们之间的实现方式有所不同,在vue源码中computed是计算属性,也就意味着,computed首先是监听参与计算变量变化,进而通知watcher进行派发更新。如果参与计算的变量没有变化,而主动更改 computed 中的变量或者变量里的属性值,只能触发computedsetter方法(前提computed是通过getset设置的)。而在本示例下,父组件是返回一个完整的testObj对象,在父组件中没有任何变量参与其中计算,这就使得我们在更改testObj的属性值时,父组件认为这个testObj并没有更新不需要触发watcher进行派发更新。因此无论是在子组件还在在父组件,通过testObj.name 展示的值都无法进行更新。

解决方案

解决这个问题的方法可以有多种
一,可以把这个变量放到data中而不是computed

data() {return {testObj: {type: Object,default: ()=>({})}}
}

二、在计算属性中使用变量,通过更改这个变量实现computed更新

data() {return {isChange: false}
}
computed: {testObj() {return {name: isChange ? '标题更改了' : '空标题' ,cb(option) {this.isChange  = true}}}
}

三、在子组件中通过变量赋值的方法,将该变量重新加上响应式
因为在vue中只要在data()中定义变量,vue就会自动为其添加响应式


props:[testObj: {type: Object,default: ()=>({})}
],
data() {return {testObj_: {}}
},
created() {
this.testObj_ = this.testObj
}

以上就是相关的优化方案。

相关内容

热门资讯

周二国际油价小幅走低 对俄制裁... 来源:环球市场播报 周二国际油价微幅下跌,此前美国总统特朗普为俄罗斯设下50天期限、使其可能避免制裁...
和讯投顾徐晨:涨跌全看银行,市... 确实,当前市场的情况让人有些无奈。之前我们担心银行板块吸金太多,导致资金无法顾及其他板块。但现在银行...
模范事迹800字作文-模范事... 篇一:模范事迹800字作文-模范事迹初中作文篇一:母亲的模范事迹我的母亲是一位普通的农村妇女,但她的...
心灵的觉悟初一作文700字(... 心灵的觉悟初一作文700字 篇一心灵的觉悟人生是一场旅程,而在这个旅程中,我们经历了许多的磨难和挫折...
我的朋友初一的作文600字(... 我的朋友初一的作文600字 篇一初一的时候,我交了一个新朋友,他叫李明。李明是一个非常聪明、善良的男...