什么是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本身已有的属性。

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

总结

🤕🤕🤕 欢迎讨论交流~

相关推荐
前端菜鸟日常7 分钟前
vue2和vue3的按需引入的详细对比通俗易懂
javascript·vue.js·ecmascript
AC-PEACE22 分钟前
Vue 中 MVVM、MVC 和 MVP 模式的区别
前端·vue.js·mvc
冷琴199633 分钟前
基于Python+Vue开发的反诈视频宣传管理系统源代码
开发语言·vue.js·python
程楠楠&M1 小时前
uni-app(位置1)
前端·javascript·uni-app·node.js
破z晓1 小时前
uniapp 整合openlayers 编辑图形文件并上传到服务器
前端·javascript·uni-app
m0_748257462 小时前
创建一个简单的spring boot+vue前后端分离项目
vue.js·spring boot·后端
祈澈菇凉2 小时前
除了Axios,如何用fetch处理403错误?
前端·javascript·vue.js
草字2 小时前
vue,vue3 keepalive没有效果,无法缓存页面include无效,keep-alive
前端·vue.js·缓存
JSON_L2 小时前
Vue Axios
前端·javascript·vue.js
狐凄2 小时前
练习题:47
开发语言·前端·javascript