zoukankan      html  css  js  c++  java
  • 数据绑定之无法检测的数据更改

    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中组件间(父子,兄弟),为什么不是双向绑定?

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

  • 相关阅读:
    new、delete和malloc、free
    重写与重载
    面向对象三个基本特征
    Js零散知识点笔记
    ES6 笔记
    js 单例模式笔记
    关于闭包的见解
    DOM笔记
    浏览器差异
    JS高级程序设计 笔记
  • 原文地址:https://www.cnblogs.com/ggymx/p/13511665.html
Copyright © 2011-2022 走看看