前端小白不迷路 - 今天来介绍下Vue2的响应式原理Object.defineProperty()

331 阅读2分钟

这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战

前言

各位掘友们晚上好,一周辛劳的工作结束,迎来了幸福的周末时光,大家周末嗨皮呀!好了,闲言少叙,一起来今天的内容- 今天来介绍下Vue2的响应式原理。

vue2的响应式原理

大家知道,vue2的响应式原理是用到了数据劫持,语法是Object.defineProperty(),这个是ES5的语法,作用就是劫持对象的某个属性,比如下面对象obj, Object.defineProperty()想要劫持这个对象,只需要把obj放在这个方法里即可,如:

<script>
    var obj = {
        name: 'loncon',
        age: 18
    }
    Object.defineProperty(obj, 'name' ,{
        get() {
            console.log(obj,'劫持了obj的name属性');
        },
        set() {

        }
    })
//参数一: 对象
//参数二: 属性
//参数三: 选项
</script>

在控制台输入obj.name,打印的结果如下:

image.png 如上图,name 属性被劫持了,打印处理的结果展开就是undefined,但是我们肯定要用这个属性,是所以要return出劫持的对象的内容。

get() {
    console.log(obj,'劫持了obj的name属性');
    return obj.name
},

可是这样做是不对的,因为return出的name继续被劫持,依次进行,就会递归,进入死循环。

如何处理

劫持之前把值存起来

<script>
    var obj = {
        name: 'loncon',
        age: 18
    }
    var name = obj.name
    Object.defineProperty(obj, 'name' ,{
        get() {
            console.log(obj,'劫持了obj的name属性');
            return name
        },
        set() {

        }
    })
</script>

这样就可以拿到劫持的name属性值:

image.png

如何设置属性

利用set,就可以设置,不仅会改属性值,还可以更新dom,因为你是设置属性值,就不会走get函数了。

 set(value) {
    console.log('set函数执行了');
    name = value
}

image.png

vue内部如何操作

vue就是利用set函数,会把obj中所有的数据都进行劫持,然后更改就会改变属性的值。源码分析如下:

<script>
    var obj = {
        name: 'loncon',
        age: 18
    }
    for(var k in obj) {
        var item = obj[k]
        Object.defineProperty(obj, k ,{
        get() {
            console.log(obj,'劫持了obj的name属性');
            return name
        },
        // 只要设置name属性, obj.name = '设置值'
        set(value) {
            console.log('DOM更新');
            item = value
        }
    })
    }
</script>

image.png

Object.defineProperty()语法的缺陷:

  1. 一次只能劫持一个属性,因为不是劫持对象,所以如果对象有很多属性,需要一个个的劫持。 2.如果对象新增一个属性,那这个属性不是响应式的 比如:

image.png 这个新增的属性,没有打印DOM更新,说明这个属性没有被劫持到。

缺陷3: 天生劫持不了数据的下标和长度

后记

好了,小伙伴们,今天的分享就到这里了,下次我们用案例来讲vue2中响应式原理的缺陷及vue3的响应式原理,再会~