// 假设obj的age为私有属性 , 需要通过getter和setter来访问和设置const obj = {name: 'curry',_age: 30,get age() {return this._age},set age(newValue) {this._age = newValue}}const objProxy = new Proxy(obj, {get: function(target, key, receiver) {console.log(`obj对象的${key}属性被访问啦!`)return Reflect.get(target, key, receiver)},set: function(target, key, newValue, receiver) {console.log(`obj对象的${key}属性被设置啦!`)Reflect.set(target, key, newValue, receiver)}})// 设置:objProxy.name = 'kobe'objProxy.age = 24// 访问:console.log(objProxy.name)console.log(objProxy.age)再来看一下打印结果:
文章插图
也可以打印receiver , 在浏览器中进行查看 , 其实就是这里的objProxy:

文章插图
5.响应式原理的实现5.1.什么是响应式呢?
当某个变量值发生变化时 , 会自动去执行某一些代码 。如下代码 , 当变量num发生变化时 , 对num有所依赖的代码可以自动执行 。
let num = 30console.log(num) // 当num方式变化时 , 这段代码能自动执行console.log(num * 30) // 当num方式变化时 , 这段代码能自动执行num = 1- 像上面这一种自动响应数据变化的代码机制 , 就称之为响应式;
- 在开发中 , 一般都是监听某一个对象中属性的变化 , 然后自动去执行某一些代码块 , 而这些代码块一般都存放在一个函数中 , 因为函数可以方便我们再次执行这些代码 , 只需再次调用函数即可;
在响应式中 , 需要执行的代码可能不止一行 , 而且也不可能一行行去执行 , 所以可以将这些代码放到一个函数中 , 当数据发生变化 , 自动去执行某一个函数 。但是在开发中有那么多函数 , 怎么判断哪些函数需要响应式?哪些又不需要呢?
- 封装一个watchFn的函数 , 将需要响应式的函数传入;
- watchFn的主要职责就是将这些需要响应式的函数收集起来 , 存放到一个数组reactiveFns中;
const obj = {name: 'curry',age: 30}// 定义一个存放响应式函数的数组const reactiveFns = []// 封装一个用于收集响应式函数的函数function watchFn(fn) {reactiveFns.push(fn)}watchFn(function() {let newName = obj.nameconsole.log(newName)console.log('1:' + obj.name)})watchFn(function() {console.log('2:' + obj.name)})obj.name = 'kobe'// 当obj中的属性值发送变化时 , 遍历执行那些收集的响应式函数reactiveFns.forEach(fn => {fn()})
文章插图
5.3.收集响应式函数的优化
上面实现的收集响应式函数 , 目前是存放到一个数组中来保存的 , 而且只是对name属性的的依赖进行了收集 , 如果age属性也需要收集 , 不可能都存放到一个数组里面 , 而且属性值改变后 , 还需要通过手动去遍历调用 , 显而易见是很麻烦的 , 下面做一些优化 。
- 封装一个类 , 专门用于收集这些响应式函数;
- 类中添加一个notify的方法 , 用于遍历调用这些响应式函数;
- 对于不同的属性 , 就分别去实例化这个类 , 那么每个属性就可以对应一个对象 , 并且对象中有一个存放它的响应式数组的属性reactiveFns;
class Depend {constructor() {// 用于存放响应式函数this.reactiveFns = []}// 用户添加响应式函数addDependFn(fn) {this.reactiveFns.push(fn)}// 用于执行响应式函数notify() {this.reactiveFns.forEach(fn => {fn()})}}const obj = {name: 'curry',age: 30}const dep = new Depend()// 在watchFn中使用dep的addDependFn来收集function watchFn(fn) {dep.addDependFn(fn)}watchFn(function() {let newName = obj.nameconsole.log(newName)console.log('1:' + obj.name)})watchFn(function() {console.log('2:' + obj.name)})obj.name = 'kobe'// name属性发生改变 , 直接调用notifydep.notify()
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 您与这个网站的连接不安全?教你用python轻松解决
- 带状疱疹饮食注意什么
- 给你一个团队,你该怎么带?做好这五点,团队大变样!
- 春天到了,30种野菜辨别图片,带你认识不同的野菜和吃法
- 红烧带鱼烧豆腐的做法
- 吃野菜,带你进入健康地带
- 无神之界|我拼尽全力考上的二本,难道带给我的只能是耻辱吗?女研究生痛哭中发出灵魂之问
- 韩国|开放的“韩国”现状,带你看看真实的韩国
- 黄瓜|恩克减肥34天后回归,体重不降反增加,网友:安全带尽力了
- 大一新生入学必备清单 上大学要带什么东西
