Vue中如何在保留原有data数据的同时使isLandscape变量成为响应式变量?
解决Vue中扩展外部数据对象时响应式失效的问题
这个问题的核心原因是:Vue 2的响应式系统只会对data()返回对象的顶层属性进行劫持和依赖收集,而你直接给$f7route.context这个外部对象添加的isLandscape和componentTexts属性,并没有被Vue的响应式系统处理,所以即使值变化了,视图也不会更新。
下面给你两种可行的解决方案,既能保留原有数据,又能让isLandscape成为响应式变量:
方案一:展开外部对象属性到返回的顶层对象中
把$f7route.context的属性展开到data()返回的对象里,同时添加你的自定义属性,这样所有顶层属性都会被Vue处理成响应式:
data() { // 先获取外部数据 const routeContext = this.$f7route.context; const componentTexts = this.$LocaleHelper.getComponentTexts(componentName); // 展开所有属性到顶层,确保Vue能处理响应式 return { ...routeContext, componentTexts, isLandscape: false, } }
这样你的模板不需要修改,依然可以直接使用isLandscape、componentTexts以及原来routeContext里的属性,所有值变化都会同步到视图。
方案二:使用$set给外部对象添加响应式属性
如果你需要保留原来的对象结构(不想展开属性),可以用Vue提供的$set方法,在组件初始化后给外部对象添加响应式属性:
data() { const routeContext = this.$f7route.context; return { // 把外部对象作为顶层属性返回 data: routeContext, isLandscape: false, } }, created() { // 使用$set添加响应式属性到data对象 this.$set(this.data, 'componentTexts', this.$LocaleHelper.getComponentTexts(componentName)); // 如果想把isLandscape也放到data对象里,同样用$set: // this.$set(this.data, 'isLandscape', false); }
注意这种方式下,模板里的属性需要改成嵌套访问(如果把isLandscape放到data对象里的话):
<!-- 若isLandscape是顶层属性,保持原写法即可 --> <button v-bind:class="isLandscape ? 'red' : 'blue'" @click="log">{{isLandscape}}</button> <!-- 若isLandscape放到了data对象里,修改为: --> <!-- <button v-bind:class="data.isLandscape ? 'red' : 'blue'" @click="log">{{data.isLandscape}}</button> -->
为什么原来的方法不生效?
当你直接修改$f7route.context这个外部对象时,这个对象并不是Vue创建的响应式对象,Vue无法感知到你新增的属性变化。而当你直接返回{isLandscape: false}时,这个属性是Vue初始化时处理的顶层属性,所以能正常触发视图更新。
内容的提问来源于stack exchange,提问作者Laterneman
相关产品推荐
相关产品推荐

