Vue学习-数据响应式原理

👉 数据响应式

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

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

👉 语法

Object.defineProperty(obj, prop, descriptor)

查看更多

  • obj: 要定义属性的对象。
  • prop: 要定义或修改的属性的名称或 Symbol 。
  • descriptor: 要定义或修改的属性描述符。

共享以下可选键值:

configurable
当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
默认为 false。

enumerable
当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。
默认为 false。

数据描述符还具有以下可选键值:

value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为 undefined。writable
当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。
默认为 false。

👉 实践

<div id="app">
  hello
</div>
// 模拟 Vue 中的 data 选项
let data = {
    msg: 'hello'
}

// 模拟 Vue 的实例
let vm = {}

// 数据劫持:当访问或者设置 vm 中的成员的时候,做一些干预操作
Object.defineProperty(vm, 'msg', {
  enumerable: true,
  configurable: true,
  get () {
    console.log('get: ', data.msg)
    return data.msg
  },
  set (newValue) {
    console.log('set: ', newValue)
    if (newValue === data.msg) {
      return
    }
    data.msg = newValue
    // 数据更改,更新 DOM 的值
    document.querySelector('#app').textContent = data.msg
  }
})

vm.msg = 'Hello World'
console.log(vm.msg)

// set:  Hello World
// get:  Hello World
// Hello World

那假设是有多属性的对象呢?需要如何绑定。

核心思路就是递归遍历对象,将对象内的所有属性都绑定。

let data = {
    msg: 'hello',
    age: 18
}

let vm = {}

proxyData(data)

function proxyData(data){
    Object.keys(data).forEach(key => {
        // 把 data 中的属性,转换成 vm 的 setter/setter
        Object.defineProperty(vm, key, {
            enumerable: true,
            configurable: true,
            get () {
                console.log('get: ', key, data[key])
                return data[key]
            },
            set (newValue) {
                console.log('set: ', key, newValue)
                if (newValue === data[key]) {
                    return
                }
                data[key] = newValue
                // 数据更改,更新 DOM 的值
                document.querySelector('#app').textContent = data[key]
            }
        })
    })
}

简单了解数据劫持后,我们来看看完整流程。Vue初始的时候,将data中的数据通过 Observe 数据劫持 后,将数据利用观察者模式来监控,当事件触发时,通过 发布者Dep 去调用 观察者Watcher 的方法来更新视图。

 

了解大致流程后,我们从基础出发,理解Vue中的设计模式: 发布/订阅模式观察者模式。后面会针对这两点继续深入。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页