vue原理进阶之数据响应式

44 篇文章 0 订阅
20 篇文章 0 订阅

2.1 响应式是什么

一旦数据发生变化,我们可以立刻知道,并且做一些你想完成的事情,这些事情包括但不限于以下:

  • 发送一个网络请求
  • 打印一段文字
  • 操作一个dom

2.2 如何实现数据响应式

在Javascript里实现数据响应式一般有俩种方案,分别对应着vue2.x 和 vue3.x使用的方式,他们分别是:

1.对象属性拦截 (vue2.x)

Object.defineProperty

2.对象整体代理 (vue3.x)

Proxy

其中对象属性拦截,是我们本次课程关注的重点,不管使用其中的哪种方式,道理都是相通的

2.3 实现对象属性拦截

字面量对象定义

let data = {
    name:'柴柴老师'
}

Object.defineProperty对象定义

let data = {}
Object.defineProperty(data,'name',{
    // 访问name属性就会执行此方法 返回值就是获取到的值
    get(){
       console.log('name属性被获取了')
       return '柴柴老师'
    },
    // 设置新值就会执行此方法 newVal就是设置的新值
    set(newVal){
       console.log('name属性被设置新值了')
       console.log(newVal)
    }
})

2.4 优化1- get和set联动

上一小节,我们的get方法中返回的值始终是柴柴老师,是固定的,set中拿到新值之后,我们如何让get中可以得到newVal使我们需要解决的问题

现存问题

let data = {}
Object.defineProperty(data,'name',{
    // 访问name属性就会执行此方法 返回值就是获取到的值
    get(){
       console.log('name属性被获取了')
       return '柴柴老师'
    },
    // 设置新值就会执行此方法 newVal就是设置的新值
    set(newVal){
       console.log('name属性被设置新值了')
       console.log(newVal)
    }
})

错误演示
在这里插入图片描述

解决方案

我们可以 通过一个中间变量 _name 来中转get函数和set函数之间的联动

let data = {}
let _name = '柴柴老师'
Object.defineProperty(data,'name',{
    // 访问name属性就会执行此方法 返回值就是获取到的值
    get(){
       console.log('name属性被获取了')
       return _name
    },
    // 设置新值就会执行此方法 newVal就是设置的新值
    set(newVal){
       console.log('name属性被设置新值了')
       console.log(newVal)
       _name = newVal
    }
})

结果验证
在这里插入图片描述

2.5 优化2-更加通用的劫持方案

大家想想看,如果现在有一份已经声明好了数据的对象,我们如何通过劫持的方法把每一个属性都变成setter和getter的形式

一份已经声明好的数据

let data = {
    name: '柴柴老师',
    age: 18,
    height:180
}

我想让里面所有的属性都变成响应式的,并且get和set方法中对于每个属性值的操作是连通的

let data = {
    name: '柴柴老师',
    age: 18,
    height:180
}

// 遍历每一个属性
Object.keys(data).forEach((key)=>{
    // key 属性名
    // data[key] 属性值
    // data 原对象
    defineReactive(data,key,data[key])
})
// 响应式转化方法
function defineReactive(data,key,value){
    Object.defineProperty(data,key,{
        get(){
           return value
        },
        set(newVal){
          value = newVal 
        }
    })
}

结构说明:这个地方实际上使用了闭包的特性,看下图,在每一次的defineReactive函数执行的时候,都会形成一块独立的函数作用域,传入的value
因为闭包的关系会常驻内存,这样一来,每个defineReactive函数中的value 会作为各自set和get函数操作的局部变量

2.6 响应式总结

1.所谓的响应式其实就是拦截对象属性的访问和设置,插入一些我们自己想要做的事情
2.在Javascript中能实现响应式拦截的方法有俩种,Object.defineProperty方法和Proxy对象代理
3.回归到vue2.x中的data配置项,只要放到了data里的数据,不管层级多深不管你最终会不会用到这个数据都会进行递归响应式处理,所以要求我们如非必要,尽量不要添加太多的冗余数据在data中
4.需要了解vue3.x中,解决了2中对于数据响应式处理的无端性能消耗,使用的手段是Proxy劫持对象整体 + 惰性处理(用到了才进行响应式转换)

上述资料转载自:vue高级进阶课程

写在最后

✨个人笔记博客✨

星月前端博客
http://blog.yhxweb.top/

✨原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!

✏️评论,你的意见是我进步的财富!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星月前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值