vue2和vue3中父级属性改变,子组件props属性未改变,且不能触发监听的问题解决及响应式原理分析
1|0场景:
- 调用自定义组件的时候,父级传给子组件的值可能是异步的,然后这也分两种情况
- 子组件的值只需要在初始化时获取,之后就不变了
- 子组件的值还会变化,在后面的操作中有异步请求,跟随父级拿到的数据变化
- 这时会有父级已经请求拿到数据了,但是子组件的值还没变,也没有触发回显,界面没有改变
2|0解决:
2|1vue2
- 虽然都是响应式的问题,但是解决思路可以不一样,但其实也可以一样
- 总体来说有几种解决方法:
- 用v-if控制组件在拿到数据之后再渲染,这很明显只能解决第一种情况,不适用于第二种,但是其实这个方法并不是从本质解决问题,而是投机取巧,但是还是记录一下吧:
- 网上很多博客说在子组件内用watch监听父级传过来的props,具体实现就不说了,比较简单。而且主要是因为这个方案也不是问题的根本,它甚至在我遇到的情况中并不管用,具有局限性。我遇到的这种情况的本质是父级在改变变量值的时候,并不是响应式的,所以不能触发子组件一起变化,甚至不能触发子组件的监听函数,尝试后发现,监听函数根本进不去。
- 本质:触发响应式
- vue响应式原理官方文档,强烈建议看一看
- 这里看下文档里的监测变化的注意事项这里,有几种特殊情况是非响应式的
- 对于对象变量,如果在声明时有指明的默认属性名,那么这些属性的变化是响应式的,但是如果是没有声明的额外属性,就是非响应式,官方例子:
- 对于数组,如果是用索引修改了数组的某一项,或修改数组长度,都是非响应式的,看官方例子:
- 我就是这种情况,而且对象和数据我都遇到了,解决办法:
- 对象型,可以在声明时直接初始化默认属性值,防止额外属性的出现。或者麻烦一点,重新对整个对象赋值
- 数组型,可以用Array.splice方法来替换指定位置的值,不用索引,如
arr.splice(index, 1, newValue)
- 对象型和数组型,都可以用
this.$set(item, index/property, val)
来强制响应,如:
2|2vue3
- vue3的组件是没有this的,所以很多this相关的用法都是改了的,其中this.$set是被摒弃的
- vue3中用ref和reactive做响应式声明,这两个属性的用法算是vue3的基础,需要熟练掌握
- ref一般用于基本类型声明
- 除了string, number, boolean等类型,也可以是对应的[],如
const var1 = ref<string[]>([])
- ref在js/ts中引用和修改的时候,都需要取value属性才行,如
var1.value.push('一个值')
,这样才能正确响应 - ref在template中引用则不需要取value属性,直接用就行,如
<div v-for="item in var1">{{ item }}</div>
- 除了声明响应式变量以外,ref还用于同vue2一样对HTMLElement的标记
<div ref="test">标记</div>
,在vue2中调用ref标记的dom是用this.$refs.test
,而如果是子组件,调用子组件的方法也可以直接this.$refs.test.func()
,这一点上个人感觉还是vue2方便,在vue3,获取标记的dom比较简单,直接声明一个标记名相同的变量就行,如const test = ref(),这样就已经拿到test标记的div了,而如果要调用子组件的方法,则还需要在子组件中暴露给外部调用的方法,非setup写法就是export里面导出,而setup写法则是defineExpose({ func })
- 除了string, number, boolean等类型,也可以是对应的[],如
- reactive一般用于对象类型声明
- 如
const obj = reactive({ name: '对象' })
,在js/ts和template中都直接用其对应属性
- 如
- ref一般用于基本类型声明
- 好啦,总结就是,只要变量变化时是响应式的,子组件就能一起变化,所以出现子组件不响应的情况时,首先看看父级的变量是不是响应式的
__EOF__

本文作者:Mizuki
本文链接:https://www.cnblogs.com/mizuki-vone/p/16442726.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/mizuki-vone/p/16442726.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库