vue2学习笔记8 - 通过object.defineProperty理解Vue的响应式原理(setter/getter)

前言

常看到说Vue是响应式的,或者说,它把data中的各种属性通过Object.defineProperty转换成setter/getter,以使得vue能够追踪这些属性的变更,从而适时通知页面重新渲染或者修改Model中的值,从而实现数据的双向传递。

1、初识Object.defineProperty

ES5 提供了 Object.defineProperty 方法,该方法可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
语法

Object.defineProperty(obj, prop, descriptor)

参数

  • obj: 要在其上定义属性的对象。

  • prop:  要定义或修改的属性的名称。

  • descriptor: 将被定义或修改的属性的描述符。

如下代码:定义一个person,其中有两个属性,name和address。想要添加一个属性age,可以像前两个属性一样添加,也可以使用Object.defineProperty添加。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Object.defineProperty</title>        
    </head>
    <body>        
        <script type="text/javascript" >            
            //定义一个person,给两个属性
            let person = {
                name: "aaa",
                address: "北京"
                //age:18
            }
            //通过defineProperty增加一个属性:age
            Object.defineProperty(person,'age',{value:18})
            //打印,看看效果
            console.log(person)        
        </script>
    </body>
</html>

运行:

这两种方式,初始效果相同,但是,使用Object.defineProperty添加的属性,有一些特殊的约束条件和配置项:

1)使用Object.defineProperty添加的属性,默认情况下,不可被枚举(遍历)

2)使用Object.defineProperty添加的属性,默认情况下,不可被修改

3)使用Object.defineProperty添加的属性,默认情况下,不可以被删除

以上,可以通过相应的配置项来修改其设置:

Object.defineProperty(person,'age',{
                value:18,
                enumerable:true,    //控制属性是否可以被枚举,默认为false
                writable:true,      //控制属性是否可以被修改,默认为false
                configurable:true   //控制属性是否可以被删除,默认为false
            })

修改后,在console中试试效果(修改前,这几项操作是失败的): 

除了以上几个设置外,Object.defineProperty还有一个更重要的功能,setter和getter

2、setter/getter

提一个新的需求,age这个属性的值,希望通过另一个变量获得,而不仅仅通过直接赋值得来,且二者应该能够保持同步(这是实际业务中很常见的需求)。那么,稍稍修改一下代码,定义一个变量,并传值给age:

运行,可以看到,age成功拿到了number中的值,初始化成功。

但是,如果number发生了变化,age却无法跟着同步变化。如下图,我将number变更为19,查看person的age属性,仍然是18。

想要实现二者绑定并同步更新,就需要用到Object.defineProperty的setter和getter了。修改代码如下:

执行,此时观察age的值,并不直接显示,而是一组省略号:

当点击这三个小点时,观察console中打印出getter中的信息,说明此时触发了getter函数,读取并返回了number,即age的值。

此时修改number=19,再次打印person.age,它会自动调用getter,从而获取到最新的number并返回,实现了

同理,试一试setter:

这种number和person.age的数据同步,像不像我们之前所学的v-model实现的双向绑定?

3、Vue中的setter/getter

Vue便是通过Object.defineProperty,将data中的各属性转换成setter/getter,来实现追踪和变更这些属性的值。每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。官网中的图片:

虽然vue的setter和getter提供了很强大的数据同步功能,帮我们处理了view和model间的数据传递问题,但是,官网中有一句很重要的话:Vue不能检测数组和对象的变化。今天就因这句话出了错,回头单独说一说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值