• Vue数据监测(响应式)原理、Object.defineProperty() 实现数据代理


    Object.defineProperty()

    Object.defineProperty()的基本属性和实现简单的数据代理(也叫数据劫持)

    // 使number数据和person.age相互关联
    let number = 18
    let person = {
      name: 'zhangsan',
      sex: 'male'
    }
    
    // 给person对象添加age属性
    Object.defineProperty(person, 'age', {
      // value: 18,
      // enumerable: true, // 控制属性是否可以枚举,默认为false
      // writable: true, // 控制属性是否可以被修改,默认为false
      // configurable: true, // 控制属性是否可以被删除,默认为false
    
      // 当有人读取person中的age属性时,get函数(getter)就会被调用,且返回值就是age的值
      get() {
        return number
      },
    
      // 当有人修改person中的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
      set(val) {
        number = val
      }
    })
    

    console控制台图示

    仔细看下图会发现这里其实比正常的对象多出了get()和set()两个方法

    另外要注意这里的age属性值age: (...)和其他属性值的区别,其实用Vue的时候经常会见到这种格式,只有点一下才会显示出age的值,这是因为这里的age是用get()做了数据劫持,只有在访问的时候才会获取新的值,Vue中就是用这样的方式实现监听数据改变的

    observer-agent

    Vue中监测数据的原理

    Vue深入响应式原理

    <div id="app">{{name}}</div>
    
    const vm = new Vue({
      el: '#app',
      data: {
        name: 'zhangsan'
      }
    })
    

    vm实例data中的name数据之所以能用this.name访问(这里的this就是vm实例对象),实际上是Vue在vm实例上和vm._data做了数据代理(响应式),访问vm.namevm._data.name是一样的,如下图

    observer-vue

    模拟Vue监测数据的一个简单例子

    const data = {
      name: 'zhangsan'
    }
    
    // 创建一个监视的实例对象,用于监视data中属性的变化
    const obs = new Observer(data)
    
    // 模仿vue的操作(真正的Vue中要复杂得多~)
    let vm = {}
    vm._data = data = obs
    
    function Observer(obj){
      // 获取data中所有属性名
      const keys = Object.keys(obj)
      // 遍历每个属性,给每个属性添加get,set
      keys.forEach(k => {
        Object.defineProperty(this, k, {
          get() {
            return obj[k]
          },
          set(val) {
            obj[k] = val
          }
        })
      })
    }
    

    console控制台图示

    observer-obj

    补充 - Vue中对对象、数组添加属性

    对象

    上面说到Vue中的data数据在使用之前其实被做了一次处理(即添加了get()和set()方法,当然Vue中的处理还是比较复杂的,比如对象做了深度处理,这里只做了简单示例),这样才能保证数据更新后页面及时同步渲染

    但是在写Vue项目时,如果需要给data中的对象添加一个属性,例如:

    const vm = new Vue({
      el: '#app',
      data: {
        person: {
          name: 'zhangsan',
          sex: 'male'
        }
      },
      mounted() {
        this.person.age = 18
      }
    })
    

    此时若查看person可以发现age属性并没有被添加get()和set()方法,也就是说age属性的改变并不能使页面及时更新,如下图:

    observer-obj-add

    所以Vue官方给出了Vue.set()方法(Vue实例是vm.$set()),用于给对象或者数组添加响应式属性值,通俗来说也就是给新加的属性也有对应的get()和set()方法。

    const vm = new Vue({
      el: '#app',
      data: {
        person: {
          name: 'zhangsan',
          sex: 'male'
        }
      },
      mounted() {
        // this.person.age = 18
        this.$set(this.person, 'age', 18)
      }
    })
    

    此时的age属性已经被添加了get()和set()方法,如下图:

    observer-obj-set

    数组

    对于数组来说,Vue对数组的操作方法做了包裹,这些方法包含:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

    详情查看数组变更方法

    也就是说修改数组属性不要指定index直接操作,要使用上述方法修改,或者用vm.$set()

    完结~
  • 相关阅读:
    数据库学习笔记3--基本的SQL语句
    数据库学习笔记2--MySQL数据类型
    数据库学习笔记1----MySQL 5.6.21的安装和配置(setup版)
    JavaWeb学习笔记1---http协议
    Spring学习笔记18--通过工厂方法配置Bean
    Spring学习笔记17--在XML中使用SPEL
    Spring 学习笔记16---properties文件的两种方式
    Spring学习笔记15--注解Bean
    Spring4.0学习笔记1---开发环境搭建
    Installed JREs时 Standard 1.1.x VM与Standard VM的区别
  • 原文地址:https://www.cnblogs.com/lwlblog/p/15181134.html
Copyright © 2020-2023  润新知