数据绑定之无法检测的数据更改

Vue组件内是双向绑定,组件间(比如父子通讯)是单向绑定(react无论组件内外都是单向数据绑定),但有三种情况下,更改组件内的数据不会自动刷新视图

1:Vue不能检测到已有对象属性的添加或删除

错误写法:this.$data.test.a=xxx

正确写法:vue.set(object,key,value)Object.assign()

示例:

<script>
  export default{
    name:'Item',
    data(){
      return{
        pagition:{

        }
      }
    },
    create(){
      this.getList()
    }
    getList(){
         //request请求
        getCurrentList(data).then(res=>{
          //可以赋值,但不会引起视图刷新
          this.pagition.size=res.size
          this.pagtion.current=res.current
          //正确写法
          this.$set(this.pagition,'size',res.size)
          this.$set(this.pagition,'current',res.current)
          //也可以直接复制
          this.pagition=Object.assign({},{size:res.size,current:res.current})
        })
    }
  }
</script>

如:
1. this.$set(this.test,’a’,xxx)Vue.set(this.test,’a’,xxx)

2. this.test=Object.assign({},this.test,{a:xxx})

2:通过改动两种方式改动数组时,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);

总结:

  • 1.只有在组件data中已经定义的对象的属性直接赋值才可以引起视图刷新,对于对象的新增属性,需要使用$set赋值或者对data中已存在对象进行整体赋值才能刷新视图

  • 2.对象新增属性时直接赋值时,watch无法监听。watch可以监听$set引起的变动,因为watch内部监听的是数据的setter,已存在的属性在data初始化时已经绑定了getter/setter

  • 3.对于能够已经在data中声明过的属性,可以直接进行赋值。虽然此时使用$set也可以。但是此时$set没有直接赋值性能好(因为已存在属性赋值只会调用内部setter,而$set会先对值进行setter绑定,然后在调用settter,多走了一步)

原理:当你把一个普通的JavaScript对象传给Vue实例的data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。

这些getter/setter对用户来说是不可见的,但是在内部他们让vue追踪依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的watcher实例对象,它会在组建渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

属性的删除用$delete,用js的delete关键字不会引起视图刷新,因为
$delete不会调用数据的setter


拓展:
可以直接引起视图刷新的赋值的js的API(对data中已存在的属性而言)
push:数据尾插入
pop:尾删除
unshift:头插入
shift:头删除
splice:插入并删除
...
这些js的api会操作调用它的对象,会直接修改原数据,vue默认对它们进行了特殊处理。调用这些api会在内部调用数据的setter,从而引发视图刷新

settter的工作流程
image.png

能否用watch实现对象和数组内属性的直接修改导致视图自动刷新?

对象和数组内属性的直接修改不能刷新视图,是因为vue内监听数据的层级是一级,不会监听data中声明的数据里的数据,因此在watch中依然不行,如果是直接对data中数据进行赋值或者使用特定api,则没有必要使用watch。

watch应用场景:假如v-model 输入框绑定一个变量a 可以输入改变变量a 另一个文本绑定变量b ,他俩不是一个变量 但是b又随着a变化而变化,这样的话就用到watch了

vue中组件间(父子,兄弟),为什么不是双向绑定?

如果父子组件通讯是双向的话 则父变子变,子变父变,子父改变无穷尽也,可能会死循环。兄弟组件也一样

原文地址:https://www.cnblogs.com/ggymx/p/13511665.html