Vue组件内是双向绑定,组件间(比如父子通讯)是单向绑定(react无论组件内外都是单向数据绑定),但有两种情况下,更改组件内的数据不会自动刷新视图
一:Vue不能检测到对象属性的添加或删除
错误写法:this.$data.test.a=xxx
正确写法:vue.set(object,key,value)或者Object.assign()
如:1. this.$set(this.test,’a’,xxx) 或者Vue.set(this.test,’a’,xxx)
2. this.test=Object.assign({},this.test,{a:xxx})
二:通过改动两种方式改动数组时,Vue检测不到变动:1.利用索引直接设置一个项;2.修改数组长度。
2.1 利用索引直接设置一个项,不能直接触发状态更新。
错误写法:this.trees[idx]=’x’
正确写法:this.$set(this.trees,idx,’x’)
this.trees.splice(idx,1,’x’)
2.2 改变数组长度
错误写法:this.trees.length=2;
正确写法:this.trees.splice(2);
总结:在一个组件实例中,只有在data里初始化的数据才是响应的,没有在data里声明的属性不是响应的。即vue监听data里面声明的数据,但不监听data中数据里的数据,基于此,直接将更改后的数组和对象直接赋值也可以
原理:当你把一个普通的JavaScript对象传给Vue实例的data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。
这些getter/setter对用户来说是不可见的,但是在内部他们让vue追踪依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的watcher实例对象,它会在组建渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。
问题:
能否用watch实现对象和数组内属性的直接修改导致视图自动刷新?
对象和数组内属性的直接修改不能刷新视图,是因为vue内监听数据的层级是一级,不会监听data中声明的数据里的数据,因此在watch中依然不行,如果是直接对data中数据进行赋值或者使用特定api,则没有必要使用watch。
watch应用场景:假如v-model 输入框绑定一个变量a 可以输入改变变量a 另一个文本绑定变量b ,他俩不是一个变量 但是b又随着a变化而变化,这样的话就用到watch了
vue中组件间(父子,兄弟),为什么不是双向绑定?
如果父子组件通讯是双向的话 则父变子变,子变父变,子父改变无穷尽也,可能会死循环。兄弟组件也一样