什么是vue2.x中Object的变化侦测?

痛定思痛,总要静一静,用抹布抹一抹陈旧模糊的记忆。

虽然截止至2023年12月31日,vue2.x版本已停止维护,但是vue2中的很多东西还是值得去思考的。

最经典的面试题莫过于:简述下Vue2的响应式原理~🤦‍♂️

what ?

什么是变化侦测?

说白话,就是界面视图发生改变时,需要有个人告诉我视图变了。

例:元宵节夜晚,当你一路向北行进时,背后方向忽然放起了烟花秀。迎面而来的一位美女,告诉了你。你转身回望赞叹了一句:"好漂亮~"

变化的事件:烟花秀

侦测者:美女

How?

如何追踪变化?

那么绕不开的一个方法必然就是 Object.defineproperty() ,建议通读其对象属性以便加深理解与感悟。

通过对其封装,得到如下函数,其作用是定义一个响应式数据。即在其中进行变化追踪,封装的目的在于仅仅传递入参即可。

js 复制代码
function defineReactive(data,key,val){ // 封装函数
  Object.defineProperty(data,key,{
    enumerable:true,
    configurable:true,
    get:function(){ // 获取(读)数据的值
      return val;
    },
    set:function(newVal){ // 设置数据的值
      if(val === newVal){
        return;
      }
      val = newVal;
    }
  })
}

关注点

  • 每当从data的key中读取数据是,get函数被触发
  • 每当往data的key中设置数据时,set函数被触发

封装的目的:收集依赖

🤕 依赖是啥?---> 变化的信息(比如:之前提到的烟花秀)

一句话总结:先收集依赖,在getter中收集依赖,在setter中触发依赖

ps【通读 **Object.defineproperty()**后很好理解】:

getter---> get()函数对应的属性

setter---> set()函数对应的属性

存放依赖

⛏ 为啥存?---> 计算机处理数据,在输入后,需要存储才能进行后续操作。

这里定义了一个Dep类来收集、删除依赖或向依赖发送通知。

有时候,为了让自己开心,Dep可以是任何我喜欢的名字(比如:BBQ🤪)。

js 复制代码
export default class Dep {
    constructor() {
        this.subs = []
    }
    
    addSub(sub) {
        this.subs.push(sub)
    }
    
    removeSub(sub) {
        remove(this.subs, sub)
    }
    depend() {
        if(window.target) {
            this.addSub(windwo.target)
        }
    }
    
    notify() {
        const subs = this.subs.slice()
        for(let i = 0, l = subs.length; i < l; i++) {
            subs[i].update()
        }
    }
}

function remove (arr, item) {
    if (arr.length) {
        const index = arr.indexOf(item)
        if(index > -1) {
            return arr.splice(index, 1)
        }
    }
}

既然有地方存依赖了,那么响应式函数就可以改造了

js 复制代码
function defineReactive (data, key, val) {
    let dep = new Dep() // 修改
    Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get: function () {
            dep.depend() // 修改
            return val
        },
        set: function () {
            if(val === newVal) {
               return 
            }
            val = newVal
            dep.notify() // 修改
        }
    })
}

什么是watcher?

Watcher是一个中介的角色,数据变化时通知它,他负责通知其他地方。(比如:之前例子中的美女😁)

美女告诉了我背后有烟花秀,所以我才知道,并发出了赞美。

想要侦测所有

美女告诉我有烟花秀,仅仅是一件事。如果想知道更多的事应该怎么办?

答:住院

你一旦有什么事,护士会立马通知你~🤣

此时,则需要一个新的类 Observer,来实现将一个正常的Object转换成被侦测的Object。

解决方案是递归实现,此处不再展开。

关于Object的问题

如上所述,递归将一个正常的Object转换成被侦测的Object。然而,仅仅涵盖了Object本身已有的属性。

故无法追踪新增属性和删除属性

总结

🤕🤕🤕 欢迎讨论交流~

相关推荐
计算衎24 分钟前
FastAPI后端和VUE前端的数据交互原理详解
前端·vue.js·fastapi
转转技术团队26 分钟前
前端工程化实践:打包工具的选择与思考
前端·javascript·webpack
哆啦A梦158835 分钟前
商城后台管理系统 03 规格参数配置
javascript·vue.js·elementui
知其然亦知其所以然38 分钟前
JavaScript 变量的江湖恩怨:一篇文章彻底讲清楚
前端·javascript·面试
小番茄夫斯基40 分钟前
使用 pnpm + Workspaces 构建 Monorepo 的完整指南
前端·javascript·vue.js
shuaijie051843 分钟前
两个表格进行相互联动
前端·javascript·vue.js
JS_GGbond1 小时前
让代码学会“等外卖”:JavaScript异步编程趣谈
前端·javascript
随风一样自由1 小时前
React编码时,什么时候用js文件,什么时候用jsx文件?
开发语言·javascript·react.js
by__csdn1 小时前
Vue3 生命周期全面解析:从创建到销毁的完整指南
开发语言·前端·javascript·vue.js·typescript·前端框架·ecmascript
小年糕是糕手1 小时前
【C++同步练习】模板初阶
服务器·开发语言·前端·javascript·数据库·c++·改行学it