1分钟搞懂 Vue双向绑定的实现原理: Object.defineProperty

发布于 2022年 02月 10日 12:26

参考文档

developer.mozilla.org/zh-CN/docs/…

1.descriptor 有这些取值,首先你只需要记住get 和set,其他全部忘掉

2.原理

const demoDefineProperty = () => {
    let o = {
        name: 'two_k'
    }
    
    Object.defineProperty(o, 'name', {
        get: function() {
            console.log('get get')
        },
        set: function() {
            console.log('set set')
        }
    })
    
    console.log('o is', o.name)
    o.name = 'new_k'
    console.log('new o is', o.name)
}

比如定义了 Object.defineProperty(o, 'name', {}) ,那么当你访问o.name 的时候,会自动调用get 方法; 当赋值 o.name = xxx 的时候,会自动调用set 方法。 相当于 js 这门语言给你提供了一个后门,你调用o.name 会在背后做一些事情。

所谓数据双向绑定,就是 js 对象的数据变了,页面元素的值会发生变化。 那在 js 里面调用 o.name = 'XXX' 的时候,把页面元素改掉就好了,因为会自动调用 set 方法,就在 set 方法里面写。 然后在 js里面给 o.name 赋值,调用了 dom api,页面的内容就会发生改变。

同样的道理,监听输入框的事件,直接拿到对象的值: 这就是数据双向绑定的原理。

3.那为什么 vue 里面所有 key 要放在 data 里面呢?

如图中,没有放在 message 里面的东西是不会响应的。为什么呢 ?

仔细看看 Object.defineProperty 的参数,第一个参数是对象, 第二个参数是对象的 key,你写在 message 里,他才能作为第二个参数传给 Object.defineProperty。

换言之,只有调用过 Object.defineProperty 才可以让这个属性具备双向绑定的特性。那你调用的时候要有参数呀,参数怎么来呢?总要在一个地方写死的, vue 就是规定写在 data 里面的。

app6.shit 就不会响应。因为没有放在 data 里面,没放在 data 里面就不能调用 defineProperty 的时候传过去,没传过去自然没办法具备双向绑定的性质。 所以如果想 app6.shit 起作用,就必须调用 set方法。调用set 方法。调用 set 你就可以拿到属性名字,然后就可以调用 defineProperty。

4.至于Vue要用 defineProperty 呢 ?

这个 api 是 es5 提供的,后面有 proxy 和 reflect 这两个 api。这个就是 vue 的原理啦。 实际上这个 api 就是 [ 重载 ], 换一个语言就会把这个叫做 [ 操作符重载 ]

推荐文章