在JavaScript中实现响应式一般有两种方案,分别对应着vue2.x和vue3.x使用的方式,他们分别是:

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

Object.defineProperty

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

Proxy

1.字面量定义

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

data.name = '猪猪老师' // 这种情况下我们并不知道name属性发生了变化

2. Object.defineProperty

let data = {}

Object.defineProperty(data1,'name',{

// 当我们访问data1的name属性的时候自动调用的方法(get)

        get () {

console.log('你访问了data1的属性')

return '菜菜老师'

},

// 当我们设置修改name属性的时候自动调用的函数

// 并且属性最新的值会被当做实参传进来

        set(newval){

console.log('你修改了data1的name属性最新的值为',newval)

// 所以如果你想要在name属性发生变化的时候 完成一些自己的事情

都可以放到这里执行

        例如: 1. ajax()

                 2.操作一块dom区域

}

})

当这段代码执行的时候, 在页面调试中, data1.name 会自动调用 get()函数,

打印 console.log('你访问了data1的属性') '菜菜老师'

当你设置data1.name的值时会自动调用 set()函数

 eg: 设置:data1.name = '猪猪老师' 

打印 console.log('你修改了data1的name属性最新的值为',猪猪老师)

// 以上是js中对象定义的另外一种方案,可以在访问属性和设置属性的时候自动调用对应的函数

// 访问属性指:eg data.name  data['name']

// 设置属性:eg data.name = 'pink' data['name'] = 'pink'

 这里我们可以看到。  当你设置上面代码的时候 set()函数会立即调用,所以我们可以在set()函数中完成很多自己想要做到的事情 

// 所以如果你想要在name属性发生变化的时候 完成一些自己的事情

都可以放到set()这里执行

 Object.defineProperty 的时候

 

 这个问题产生的原因: get中直接返回了一个固定值,并且set函数中的新值拿到了但是没有做任何操作

解决方案: 通过声明一个中间变量,让get函数中return出去这个变量 并且在set函数中把最新的值设置到这个中间变量身上,起到一个set和get操作的是同一个数据的效果

还有一个问题:在vue2中我们都是提前把响应式数据写在了data配置中

        eg: data() {

         return { name:'cp',height:180}       

 }

所以一般情况下,响应式数据 提前写好,并且对象很多,那么如何把这个提前写好的对象把里面的所有属性都变成我们刚刚写过的set和get的形式?

// 可以做到不管是访问data中的任何一个属性还是设置data中的任何一个属性 我们都能知道

1.由于有多个属性,所以我们需要进行一个对象的遍历

Object.keys(data) 得到的是一个数组 所以可以用forEach方法 

Object.keys(data).forEach(key =>{ console.log(key) } ) 可以发现拿到的是每一个data的属性名

属性值是 data[key] 代表data中每一个属性对应的属性值

data 源对象

 总结

1.尽量不要在一个函数中书写大量的逻辑。而是应该按照功能拆分成多个小函数

然后通过传参组合起来

2.对象遍历的时候,每遍历一次调用一次observe函数,形成了多个独立的函数作用域

在每一个独立函数作用域中 get和set联动操作的都是独立的value

JS原理

注意:1.函数定义形参相当于在内部,申明了和形参名字对应的变量,并且初始值为undefind

          2.函数调用传入实参,相当于在内部给申明好的变量做了赋值操作

         3.函数调用完毕,本来应该内部的所有变量都会被回收,但是如果内部有其他函数使用了当前变量则形成了闭包,不会被回收

        4.内部由于有其他方法使用了该变量,所以函数的执行并不会导致变量的销毁,一直常驻在内存中

1.所谓的响应式其实就是拦截数据的访问和设置,插入一些我们想要做的事情

2.在Javascipt中能够实现响应式拦截的方法有两个:Object.defineProperty 和 proxy对象代理

3.回归到vue2.x中的data配置项,只要放到了data里的数据,不管层级多深不管有没有用到都会进行递归响应式处理

4.需要了解vue3.x 解决vue2中对于数据响应式处理的无端性能消耗,使用的手段是Proxy劫持对象整体+惰性处理(用到了才进行响应式转换)

---------------------------------------------------------------------------------------------------------------------------------

该文章通过观看*黑马*vue原理视频讲解, 如果有兴趣的小伙伴可以去找一下观看

Logo

前往低代码交流专区

更多推荐