您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
为什么 Vue3.0 要重写响应式系统
 
作者:西岭老湿
  1499  次浏览      13
 2021-3-17  
 
编辑推荐:
本文主要介绍了为什么 Vue3.0 要重写响应式系统 ?响应式原理、Object.defineProperty 的问题、Composition API 的响应式系统等相关内容。
本文来自于bilibili,由火龙果软件Anna编辑推荐。

面试的时候经常被问到 响应式 相关的内容,而Vue3.0 更新后,面试官又有了新的武器;

面试官:为什么 Vue3.0 要重写响应式系统?

懵逼树上懵逼果,懵逼树下你和我,面试官在问什么,我该怎么回答,完全不知道怎么回事;

有些经验的小伙伴可能会从解释 Proxy 的好处开始简单聊一下,比如: Proxy 是直接代理对象,而不是劫持对象的属性;更好的数组监控;

这样的回答,勉强算是合格吧

那到底应该怎么答呢?

面试官背后的出题逻辑

别急,咱们先整理一下思路,孙子兵法有云:“知己知彼,百战不殆”;面试就像打仗,你来我往,所以我们需要换位思考,想一想,为什么面试官会问这样一个问题?面试官想从这个问题里得到什么回答?这个问题可以考察哪些技术点? 想清楚这个问题,再回到自己身上,这些技术点,你都掌握了吗?

说得直白一点,面试就像考试,你需要先 读题、审题才能答好这道题;

为什么很多人认为 “面试造火箭,工作拧螺丝”?因为没有换位思考,没有想清楚面试题背后的逻辑;

那我们想清楚这个逻辑之后,需要我们做的就是提取技术点,整理思路,做出对应解答;当然,前提是你需要具备这些技术能力

那么接下来,我就尝试拆解一下这个面试题了,提取其中的知识点。

对于你来说,就是要看看这些知识点,你都掌握了多少?

为什么 Vue3.0 要重写响应式系统 ?

为什么重写?如果之前好好的,重写就没有意义,那之前存在什么问题,现在是怎么解决的?就是关键点了;

不知道你对 Vue2.x 的响应式掌握多少,是不是欠下了技术的债呢?没关系,我来帮你还债,先梳理 Vue2.x 的响应式;

其实基于这个面试题,背后还有很多技术点,上面这些,是与当前题目有直接关系的,实际面试中,很有可能基于这些技术点,在进行深入交流,这里就不扩展了,你能把现在这些问题理清楚,就算赚到了;

Vue2.x 响应式

其实关于这一点,在Vue 的官方文档中,早已经有过说明了,而且说得非常详细;官方文档

当你把一个普通的 JavaScript 对象传入 Vue 实例作为data选项,Vue 将遍历此对象所有的 property,并使用Object.defineProperty?把这些 property 全部转为getter/setter。Object.defineProperty是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装vue-devtools来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个watcher实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

我们使用官方给的一张图示,来梳理整个流程;

我们先来看一段代码

响应式原理

data 中的 obj 就是一个普通的 JavaScript 对象,通过点击 Click 按钮,将获取到的随机数赋值给 this.message ,而 this.message 指向的就是 data 中 obj 对象的 message 属性;当message 发生数据改变时,页面中 H1 标签的内容会随之改变,这个过程就是就是响应式的;那么Vue 是如何实现的呢?

首先,Vue 内部使用 Object.defineProperty() 将 Data 中的每一个成员都转换为 getter / setter 的形式;getter用来依赖收集,setter?用来派发更新;而模板内容,最终会被编译为 render 函数,在 render 函数中,我们能发现_v(_s(message))?message 被访问了,就会触发 getter 来进行依赖收集,而在代码中的点击事件中,一旦事件处理程序被触发执行,那么 message 则会被修改,就会触发 setter来进行派发更新;

虽然流程理清楚了,但是总感觉少点什么,怎么才能更通透呢?

我们用代码来模拟整个的实现过程;

defineProperty 模拟代码

defineProperty 的基本用法,直接看手册就行了:

我们来看看代码:

你没有看错,加上注释,一共 36行代码,这就是 Vue2.x 对响应式实现的整个流程;

继续实现多个数据的响应式

上面的代码只是模拟了 响应式 的原理,但Vue在实现中,肯定不会那么简单,接下来,我们看一下源码呀……

Vue2 源码解读

首先找到响应式代码的处理位置:

看完Vue2.x 响应式的代码,我们再回过头来思考最开始的问题,为什么 Vue3.0 要重写响应式系统 ?

为什么重写?如果之前好好的,重写就没有意义,那之前存在什么问题,换句话问就是 defineProperty ?有什么问题?

Object.defineProperty 的问题

其实, defineProperty 的问题,在Vue2.x 的手册中,已经说过了;“哎,很多人就是不看文档啊”

下面分别使用 Vue2 和 Vue3 实现了一个小功能,代码一模一样,功能当然也一样,但是,在 Vue2 中就会有Bug,而运行在vue3中的,则没有任何问题;

Vue2:

Vue3:

其核心点在于 defineProperty 不能很好的实现对数组下标的监控,而在 Vue2 的实现代码中,没有更好的方案对此进行改善,尤大索性直接放弃了实现;关于这个问题,尤大也在 github 做过回应,截个图给大家看看;

那么,Vue 目前还没有解决的问题,Vue3中显然是已经解决的了,问题是,Vue3 是如何解决的呢?前面在 Vue3 的代码中我们使用的是传统的 Options Api 来实现的数据响应式, 而在 Vue3 中全新的 Composition Api 也实现了响应式系统,我们先来感受一下 Composition Api 的基础用法

Composition API 的响应式系统

ref 响应式

reactive 响应式

Vue3 中的响应式是如何实现的呢?关键点在于Proxy 函数;

Proxy 实现原理

使用 Proxy 实现的响应式代码,要比使用 defineProperty 的代码简单得多,因为 Proxy 天然的能够对整个对象做监听,而不需要对数据行遍历后做监听,同时也就解决了数组下标的问题;

我们来一段模拟代码看一下:

 

 
   
1499 次浏览       13
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]
 
最新文章
如何设计高扩展的在线网页制作平台
electron入门心得
使用 Electron 构建桌面应用
VUE.JS组件化开发实践
深入理解JSCore
最新课程
HTML 5 + CSS3 原理与开发应用
Web前端高级工程师必备技能实战
Vue大型项目开发实战
React原理与实践
Vue.js进阶与案例实践
更多...   
成功案例
中交集团 构建Web自动化测试框架
某著名电信公司 Vue.js进阶与案例
国电通网络技术 HTML5+CSS3 +web前端框
移动通信 移动互联网应用开发原理
某电力行 android开发平台最佳
更多...