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

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

总结

🤕🤕🤕 欢迎讨论交流~

相关推荐
计算机学姐11 分钟前
基于微信小程序的调查问卷管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
一颗花生米。3 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
学习使我快乐013 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
bobostudio19953 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
勿语&4 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
黄尚圈圈4 小时前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
一路向前的月光9 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   9 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web9 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
Jiaberrr10 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui