• Vue 响应式原理 Better


    什么是响应式

    Vue采用非入侵式响应式系统,数据模型仅仅是普通的JavaScript对象。
    当修改数据时,视图会自动进行更新。

    如何追踪变化

    当把一个普通的JavaScript对象传入Vue实例,作为 data 选项。
    Vue将遍历此对象的所有的property,并使用Object.defineProperty 把这些 property 全部转为 getter/setter。
    在 property 被访问或者修改时,就会触发getter/setter,通知变更,让Vue能够追踪变化。
    每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中,把“接触”过的数据的 property 记录为依赖。
    之后,当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

    核心API Object.defineProperty

    const data = {}
    const name = 'zhangsan'
    Object.defineProperty(data, "name", {
      get: function () {
        console.log('get')
        return name
      },
      set: function (newVal) {
        console.log('set')
        return newVal
      }
    })
    
    // test
    console.log(data.name) // get zhangsan
    data.name = 'lisi' // set
    
    • 多层级对象需要用递归实现深度监听;

    限制

    由于JavaScript的限制,Vue不能直接检测数组和对象的变化。
    需要用一些方法来回避限制,保证它们的响应式。

    限制解决

    对于对象

    • 由于在初始化时,进行getter/setter转化,所以无法检测 property 的添加/移除。
      • 单个 property
        Vue.set(Object, propertyName, value) / this.$set(Object, propertyName, value)
        例:
        Vue.set(vm.someObj, 'b', 2) / this.$set(this.someObj, 'b', 2)
      • 多个 property
        // 代替 Object.assign(this.someObject, { a: 1, b: 2 })
        this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

    对于数组

    • Vue 不能检测以下数组的变动:
      • 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
      • 当你修改数组的长度时,例如:vm.items.length = newLength
        解决第一类问题
    // Vue.set
    Vue.set(vm.items, indexOfItem, newValue)
    // 或者
    vm.$set(vm.items, indexOfItem, newValue)
    
    // Array.prototype.splice
    vm.items.splice(indexOfItem, 1, newValue)
    

    解决第二类问题

    vm.items.splice(newLength)
    

    Object.defineProperty的缺点(Vue3.0启用Proxy)

    • 深度监听需要递归到底,一次性计算量大;
    • 无法监听 新增/删除 属性(Vue2解决用Vue.set / Vue.delete);
    • 无法原生监听数组,需要特殊处理(重写数组方法,在真正触发方法前,先更新视图)

    Proxy的问题

    • 兼容性不好,而且无法polyfill
  • 相关阅读:
    Python:Day02
    Python:Day01
    学习Python的第二天
    学习Python的第一天
    MySQL插入中文数据乱码问题
    MySQL数据库应用(11)DML之表和字段
    MySQL数据库应用(10)DML之修改表中的记录
    MySQL数据实战(初步增量恢复)
    MySQL数据库应用(9)DQL之select知识
    MySQL数据库应用(8)DML语句之insert知识
  • 原文地址:https://www.cnblogs.com/huangtq/p/14575509.html
Copyright © 2020-2023  润新知