面试取经:Vue篇-Vue2响应式原理

Vue2响应式原理

  1. 劫持数据属性,完成数据响应式
  2. 获取数据时,完成依赖收集工作
  3. 修改数据时,完成派发更新操作

数据劫持-Observer

vue 会遍历data中的属性,通过Object.defineProperty()给每个属性添加get和set方法

javascript 复制代码
data(){
    return {
        name:'john',
        info:{
            school:'xxx'
        }
    }
}
​
​
​
Object.defineProperty('name',{
    get(){
       // 获取时运行 
    }
    set(value){
        // 修改时运行
    }
})
​
// 针对info会深度遍历

后续,动态的添加和删除属性是无法检测的

arduino 复制代码
info.age = '18' // 检测不到
delete info.school // 检测不到

但vue提供了set和delete实现上述的检测

kotlin 复制代码
this.$set(this.info,age,'18')
this.$delete(this.info,school)

针对数组,vue修改了它的隐式原型

ini 复制代码
[1,2,3]._proto_ = defVue // Vue 自定义对象
defVue._proto_ = Array.prototype

数组存在缺陷

  • 检测不到 数组长度的变化
  • 检测不到根据索引修改元素

依赖收集-Dep

在数据劫持的过程中,vue会为响应式对象中的每个属性,对象本身,数组本身创建一个Dep实例,Dep实例可以完成记录依赖以及派发更新的工作,当读取响应式对象的某个属性时,进行依赖的收集depend()

具体依赖收集过程-Watcher

Vue在初始化时,会为每一个组件实例创建一个watcher,watcher中记录了该组件的render函数,首次挂载时,即在mounted阶段,watcher会先运行一次render函数,完成依赖的收集(将用到的响应式数据与watcher进行关联)

scss 复制代码
new Watcher(render)
​
render(){
    // this.a
    // 调用get
    // get调用时,dep.depend() 记录wather
}

派发更新-Update

当改变某个属性时,进行派发更新notify()

kotlin 复制代码
// 数据修改
this.a = '1'
// 调用set
// set调用时,dep.notify() 通知watcher运行render函数,界面重新渲染并重新记录当前依赖

更新过程-Scheduler

watcher 收到派发更新通知后,并非立即执行对应的函数,而是把自己交给一个叫做调度器的东西,由其完成,调度器维护一个执行队列,该队列同一个watcher仅会存在一次,队列中的watcher会被调度器通过nextTick函数放到事件循环的微任务队列

scss 复制代码
nextTick(){
    Promise.resolve().then(watcher)
}
相关推荐
Highcharts.js6 分钟前
如何下载使用Highcharts Grid 开发web可编辑表格
前端·人工智能·grid 表格·web 表格·在线编辑表格·highcharts表格安装·表格开发工具
用户629605932470543 分钟前
从“浏览器根本区分不了”到真正实现:刷新不退出,关闭标签页自动退出,前端判断浏览器关闭和刷新
前端
qetfw1 小时前
MWU:Vue 3 + FastAPI 的 MaaFramework 跨平台 WebUI 源码
前端·vue.js·python·fastapi·开源项目·效率工具
mfxcyh1 小时前
Vue3+Ant Design Vue 实现手动异步文件上传(含大小校验、弹窗上传)
前端·javascript·vue.js
wordbaby1 小时前
Web端热敏标签打印完整解决方案(QZ Tray + 译维A42)
前端
swipe1 小时前
03|Axios 请求进了后端之后:Controller、Request、Response 是怎么接住它的?
前端·后端·全栈
meilindehuzi_a1 小时前
Vue3进阶基础:指令修饰符、v-model表单绑定、动态样式、计算属性与侦听器实战
前端·javascript·vue.js
csdn2015_1 小时前
vue 前端运行命令
前端·javascript·vue.js
swipe1 小时前
02|从 `pnpm dev` 到 Spring Boot 启动:后端服务到底怎么跑起来?
前端·后端·全栈
swipe1 小时前
01|前端人第一次打开 Spring Boot 项目,应该先看哪里?
前端·后端·全栈