vue.js响应式原理,vue中实现响应式数据的原理

  vue.js响应式原理,vue中实现响应式数据的原理

  Vue最巧妙的特点之一是它的反应系统。下面文章主要介绍Vue.js响应式数据的一种简单实现方法,通过示例代码详细介绍。有需要的朋友可以参考一下。

  

目录

  简介基本概念副作用函数响应式数据响应式数据的基本实现思路初步实现尝试完善响应系统泛化副作用函数名称修复漏洞总结

  

引言

  在Vue.js中,Vue会自动跟踪JavaScript状态的变化,并在状态变化时更新DOM作为响应。这是Vue.js的两大核心功能之一,——响应性,是每个Vue.js框架用户必须熟练掌握的功能。得益于Vue.js本身支持的声明式渲染,大大降低了Vue.js的学习成本。即使是前端领域的小白,只要能理解并简单使用基本的HTML、JavaScript和CSS,也能快速上手Vue.js。学,真的好学;是的,真的有用!但是,你对Vue.js框架的内部实现原理了解多少呢?今天我们就简单的重现一下Vue.js的数据响应。

  

基本概念

  

副作用函数

  副作用函数是什么?顾名思义,副作用函数是指会产生副作用的函数。有什么副作用?会影响功能范围之外的其他部分。俗话说,药三分毒,既能治病,也能致病。药,会有副作用,副作用作用也是如此。

  副作用代码的示例如下:

  当执行效果函数时,它将设置正文的文本内容,从而直接或间接地影响依赖于正文文本内容的任何其他函数的执行。这是一个简单的副作用函数。

  

响应式数据

  据我所知,“响应式数据”更直白的说法应该是“副作用数据”,就像副作用函数的执行可能会影响函数范围之外的其他内容一样。“副作用数据”的变化可能会直接或间接影响依赖于该数据的所有功能。

  伪响应数据代码的例子如下:

  如上图所示,假设对象obj的文本属性值的每一次修改都会触发函数效果的重新执行,可以说对象obj是一个响应式数据。当然,在这个例子中,实际上并没有实现对obj对象的数据响应。

  

响应式数据的基本实现

  

实现思路

  仔细观察和考虑上述示例后,您可能会发现在实现响应式数据时有两个关键点:

  副作用函数的执行会触发字段obj.text的读取操作,响应数据obj.text的修改会触发字段obj.text的设置操作,事情的脉络会逐渐清晰:如果我们能截获对象obj的读取和设置操作,我们会在副作用函数effect第一次读取字段obj.text的值时,将其与对象obj关联起来。之后每次重置obj.text字段的值都会再次调用效果函数,这样就可以简单实现对obj对象的响应了?

  

初步实现尝试

  现在,关键问题是:如何拦截一个对象属性的读取和设置。如果你熟悉JavaScript,你可能会想到Object.defineProperty函数和代理对象Proxy。是的,这两种方案都可以拦截对象属性的读取和设置操作。其实使用Object.defineProperty函数实现数据响应正是Vue.js 2中采用的方法,代理对象Proxy也正是Vue.js3中采用的方法。

  接下来,让我们沿着上面的思路通过代理来实现它:

  这是代理对象简单实现的数据响应,可以创建一个副作用函数effect来测试。当然,考虑到复杂多变的环境,此时的数据对应性还有很多需要改进的地方。大家加班加点,尽可能给出一个相对完善的响应式数据实现方案。

  

完善响应系统

  

泛化副作用函数名

  假设有一天,副作用的函数名不叫effect了。叫做effect1或者effect2,连副作用函数都没有一个直白的名字,变成了匿名函数,那么上面的响应系统方案显然就不行了。此时,为了满足需求,我们需要提供一个注册副作用函数的机制,从而达到副作用函数名称通用化的效果。

  注册副作用函数名称的代码示例如下:

  这样,即使是匿名函数也可以成功注册为副作用函数。注册方法如下:

  当然,此时截取数据的读取操作也需要稍作调整:

  

修复漏洞

  在许多情况下,调试是最令人头疼的事情,尤其是当你知道有一个bug,但你就是找不到解决方案来修复它。真的感觉像是在监狱里.

  现在,让我们考虑一个极端情况:如果将一个原本不存在的属性添加到响应数据对象obj中,会发生什么情况?如果不熟悉前面的内容,可以回去翻翻代码。你会发现一个惊人的事实:给原本不存在的响应式数据对象obj添加一个属性,会在这个新添加的属性和相关的副作用函数之间建立一个响应式的连接。冷静下来想一想。其实这个问题的根本原因是副作用函数和操作的目标场之间没有明确的联系。那么,如何解决呢?

  想一想,数据结构中有没有一个结构是一一对应的?是的,当然,映射是。顺着这个思路,是不是可以用映射来建立目标字段和副作用函数key-value的对应关系?当然啦!那么我们可以先将负责存储函数的变量bucket声明为一个映射Maptarget,Mapkey,Set()来存储响应数据(key)——与响应数据所有属性相关的副作用函数(value),其中Mapkey,Set存储了响应对象的属性和对应的副作用函数,这样就建立了清晰的联系。在开始优化响应代码之前,我们再想一想:bucket用WeakMap会比Map好用吗?让我实话实说。当然要用WeakMap,因为WeakMap的key是一个弱引用,不会影响垃圾收集器的工作,会在合适的时候回收。用在这里比较合适。

  具体实现代码如下:

  

总结

  一般来说,为了实现一个响应式的数据,实际上就是使用代理对象Proxy或者Object.defineProperty对象来拦截数据的读取和设置操作,并与相应的副作用函数准确绑定。那么,如果现在要求你使用Object.defineProperty对象实现数据响应,你能独立实现吗?试试看!

  关于Vue.js响应式数据的简单实现方法这篇文章到此为止。有关Vue.js响应式数据实现的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: