Vue.js实现数据响应的方法

许多前端JavaScript框架(例如Angular,React和Vue)都有自己的数据相应引擎。通过了解相应性及其工作原理,您可以提高开发技能并更有效地使用JavaScript框架。在视频和下面的文章中,我们构建了您在Vue源代码中看到的相同类型的Reactivity。

如果您观看此视频而不是阅读文章,请观看系列中的下一个视频,与Vue的创建者Evan You讨论反应性和代理。

💡 The Reactivity System

当你第一次看到它时,Vue的响应系统看起来很神奇。拿这个简单的Vue应用程序:

不知何故,Vue只知道如果价格发生变化,它应该做三件事:

  • 更新我们网页上的价格值。
  • 重新计算乘以price * quantity的表达式,并更新页面。
  • 再次调用totalPriceWithTax函数并更新页面。

但是等等,你应该会觉得奇怪,当价格变化时,Vue如何知道要更新什么,以及它如何跟踪所有内容?

这不是JavaScript编程常规的工作方式。

如果你不明白,那我们试着看看常规的JavaScript是怎么运行的。例如,如果我运行此代码:

你觉得它打印什么?由于我们没有使用Vue,它将打印10。

在Vue,我们希望每当价格或数量更新时,总计都会得到更新。我们想要:

不幸的是,JavaScript是程序性的,而不是被动的,所以这在现实生活中不起作用。为了使数据变化得到相应,我们必须使用JavaScript来使事情表现不同。

⚠️ 问题

我们需要保存计算总数的方式,以便在价格或数量变化时重新运行。

✅ 解决方案

首先,我们需要一些方法告诉我们的应用程序,“我即将运行的代码,存储它,我可能需要你在另一个时间运行它。”然后我们将要运行代码,如果价格或数量变量得到更新,再次运行存储的代码。

请注意,我们在目标变量中存储了一个匿名函数,然后调用了一个记录函数。使用ES6箭头语法我也可以这样写:

请注意,我们在目标变量中存储了一个匿名函数,然后调用了一个记录函数。使用ES6箭头语法我也可以这样写:

记录的方法:

我们正在存储目标(在我们的例子中是{total = price * quantity}),所以我们可以稍后运行它。

这将遍历存储阵列中存储的所有匿名函数并执行它们中的每一个。

然后在我们的代码中,我们可以:

很简单吧?如果您需要阅读并尝试再次掌握它,这里的代码就完整了。仅供参考,如果您想知道原因,我会以特定的方式对此进行编码。

⚠️ 问题

我们可以根据需要继续记录目标,但是有一个更强大的解决方案可以扩展我们的应用程序。那就是一个负责维护目标列表的类,当我们需要它们重新运行时,这些目标列表会得到通知。

✅ 解决方法: 使用Class

我们可以开始解决这个问题的一种方法是将这种行为封装到它自己的Class中,这是一个实现标准编程观察者模式的依赖类。

因此,如果我们创建一个JavaScript类来管理我们的依赖项(它更接近Vue处理事物的方式),它可能看起来像这样:

让它运行:

它仍然有效,现在我们的代码感觉更可靠了。只有仍然感觉有点奇怪的是target()的设置和运行。

⚠️ 问题

我们将为每个变量设置一个Dep类,并且很好地封装了创建需要监视更新的匿名函数的行为。也许观察者功能可能是为了处理这种行为。

(这只是上面的代码)

我们可以改为:

✅ 解决方案:观察者功能

在我们的Watcher功能中,我们可以做一些简单的事情:

如您所见,watcher函数接受myFunc参数,将其设置为我们的全局目标属性,调用dep.depend()以将目标添加为订阅者,调用目标函数并重置目标。

现在,当我们运行以下内容时:

您可能想知道为什么我们将target实现为全局变量,而不是将其传递到我们需要的函数中。这有一个很好的理由,这将在我们的文章结尾处揭晓。

⚠️ 问题

我们有一个Dep类,但我们真正想要的是每个变量都有自己的Dep。在我们继续之前,先存储一下数据。

让我们假设我们的每个属性(价格和数量)都有自己的内部Dep类。

当我们运行时:

由于访问了data.price值,我希望price属性的Dep类将我们的匿名函数(存储在目标中)推送到其订阅者数组(通过调用dep.depend())。由于访问了data.quantity,我还希望quantity属性Dep类将此匿名函数(存储在目标中)推送到其订阅者数组中。

如果我有另一个匿名函数,只访问data.price,我希望只推送到价格属性Dep类。

我什么时候想要在价格订阅者上调用dep.notify()?我希望在设定价格时调用它们。在文章的最后,我希望能够进入控制台并执行:

我们需要一些方法来挂钩数据属性(如价格或数量),所以当它被访问时我们可以将目标保存到我们的订阅者数组中,当它被更改时,运行存储在我们的订阅者数组中的函数。

✅ 解决方案:Object.defineProperty()

我们需要了解Object.defineProperty()函数,它是简单的ES5 JavaScript。它允许我们为属性定义getter和setter函数。在我向您展示如何在Dep类中使用它之前,先简单展示一下改函数的用法。

如您所见,它只记录两行。但是,它实际上并没有获取或设置任何值,因为我们过度使用了该功能。我们现在加回来吧。 get()期望返回一个值,而set()仍然需要更新一个值,所以让我们添加一个internalValue变量来存储我们当前的价格值。

既然我们的get和set工作正常,您认为将打印到控制台的是什么?

因此,当我们获取并设置值时,我们可以获得通知。通过一些递归,我们可以为数组中的所有项运行它

FYI,Object.keys(data)返回对象键的数组。

现在一切都有getter和setter,我们在控制台上看到了这一点。

🛠 Putting both ideas together

当像这样的一段代码运行并获得价格的价值时,我们希望价格记住这个匿名函数(目标)。这样,如果价格变化,或者设置为新值,它将触发此函数以重新运行,因为它知道此行依赖于它。所以你可以这样想。

Get =>记住这个匿名函数,当我们的值发生变化时,我们会再次运行它。

Set =>运行保存的匿名函数,我们的值刚改变。

或者就我们的Dep Class而言

Price accessed (get) => 调用dep.depend()来保存当前目标

Price set => 在价格上调用dep.notify(),重新运行所有目标

让我们结合这两个想法,并完成我们的最终代码。

现在看看会发生什么。

正是我们所希望的!价格和数量都确实是得到了实时的响应的!只要价格或数量的价值得到更新,我们的总代码就会重新运行。

Vue文档中的这个插图现在应该开始有意义了。

你看到那个漂亮的紫色数据圈了吗?看起来应该很眼熟!每个组件实例都有一个从getter(红线)收集依赖项的服务观察器实例(蓝色)。当稍后调用设置程序时,它会通知监视程序,它将导致组件重新呈现。下面是我自己的一些注释的图片。

是的,现在是不是觉得更有意义了。

显然,Vue做的可能更复杂更惊喜,但你现在知道了基础知识。

⏪ 总结:所以我们学了什么?如何创建一个Dep类来收集依赖项(依赖)并重新运行所有依赖项(notify)。如何创建一个观察程序来管理我们正在运行的代码,这些代码可能需要作为依赖项添加(target)。如何使用Object.defineProperty()创建getter和setter。

总结

以上所述是小编给大家介绍的Vue.js实现数据响应的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Vue实现动态响应数据变化

    Vue是MVVM模式,即Model-View-ViewModel,通过绑定数据即可以实时改变视图显示. 比如:使用v-blink动态绑定属性 <div v-blink:class="property"></div> 使用v-html来绑定带有标签的内容(会解析标签) <div v-blink:class="property" v-html="content"></div> 使用v-text来绑定纯文

  • 谈谈对vue响应式数据更新的误解

    对于刚接触vue的同学会经常遇到数据更新了但是模板没有更新的问题,下面将结合vue的响应式特性以及异步更新机制分析常见的错误: 异步更新带来的数据响应式误解 异步数据的处理基本是一定会遇到的,处理不好就会遇到数据不更新的问题,但有一种情况是在未正确处理的情况下也能正常更新,这就会造成一种误解,详情如下所示: 模板 <div id="app"> <h2>{{dataObj.text}}</h2> </div> js new Vue({ el

  • Vue实现双向绑定的原理以及响应式数据的方法

    一.vue中的响应式属性 Vue中的数据实现响应式绑定 1.对象实现响应式: 是在初始化的时候利用definePrototype的定义set和get过滤器,在进行组件模板编译时实现water的监听搜集依赖项,当数据发生变化时在set中通过调用dep.notify进行发布通知,实现视图的更新. 2.数组实现响应式: 对于数组则是通过继承重写数组的方法splice.pop.push.shift.unshift.sort.reverse.等可以修改原数组的方式实现响应式的,但是通过length以及直接

  • 浅谈Vue 数据响应式原理

    前言 Vue的数据响应主要是依赖了Object.defineProperty(),那么整个过程是怎么样的呢?以我们自己的想法来走Vue的道路,其实也就是以Vue的原理为终点,我们来逆推一下实现过程. 本文代码皆为低配版本,很多地方都不严谨,比如 if(typeof obj === 'object')这是在判断obj是否为为一个对象,虽然obj也有可能是数组等其他类型的数据,但是本文为了简便,就直接这样写来表示判断对象,对于数组使用Array.isArray(). 改造数据 我们先来尝试写一个函数

  • 浅谈Vue数据响应

    Vue 中可以用 $watch 实例方法观察一个字段,当该字段的值发生变化时,会执行指定的回调函数(即观察者),实际上和 watch 选项作用相同.如下: vm.$watch('box', () => { console.log('box变了') }) vm.box = 'newValue' // 'box变了' 以上例切入,我想实现一个功能类似的方法 myWatch. 如何知道我观察的属性被修改了? -- Object.defineProperty 方法 该方法可以为指定对象的指定属性设置 g

  • Vue.set()实现数据动态响应的方法

    在vue里面,我们操作最多的就是各种数据,在jquery里面,我们习惯通过下标定向找到数据,然后重新赋值 比如var a[0]=111;(希望上家公司原谅菜鸟的我写了不少这样的代码

  • vue.js实现数据动态响应 Vue.set的简单应用

    在vue里面,我们操作最多的就是各种数据,在jquery里面,我们习惯通过下标定向找到数据,然后重新赋值 比如var a[0]=111;(希望上家公司原谅菜鸟的我写了不少这样的代码) 下面上代码 <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./js/vue.min.js

  • Vue.js实现数据响应的方法

    许多前端JavaScript框架(例如Angular,React和Vue)都有自己的数据相应引擎.通过了解相应性及其工作原理,您可以提高开发技能并更有效地使用JavaScript框架.在视频和下面的文章中,我们构建了您在Vue源代码中看到的相同类型的Reactivity. 如果您观看此视频而不是阅读文章,请观看系列中的下一个视频,与Vue的创建者Evan You讨论反应性和代理.

  • vue.js实现价格格式化的方法

    这里分享一个常用的价格格式化的一个方法,在电商的价格处理中非常的实用,我们可以看一个效果 这里在价格数据的地方使用了一个过滤器,通过这个过滤器对价格做了保留小数位的处理. HTML <div class="price"> <span v-html="goods.sale_price|format"></span> <span class="price-before">¥{{"这里是价格数据"}}&l

  • vue.js实现备忘录功能的方法

    这个vue实现备忘录的功能demo是K在github上找到的,K觉得这是一个用来对vue.js入门的一个非常简单的demo,所以拿在这里共享一下. (尊重他人劳动成果,从小事做起~  demo原github地址:https://github.com/vuejs/vue) 一.实现效果 二.代码展示 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>备忘录&l

  • Vue.js实现表格渲染的方法

    我们大多时候渲染表格都是key值在页面上写死的情况下,一个个value渲染,那我们遇到数据是键值对的时候该如何渲染呢? 我们查看vue的官方文档,如下: 值域 v-for v-for 也可以接收一个整数,此时它将重复模板数次. <div> <span v-for="n in 10">{{ n }} </span> </div> 结果: 那我们就可以通过如下方法来渲染列表: <table class="table table

  • 解决使用Vue.js显示数据的时,页面闪现原始代码的问题

    今天开始学习Vue.js的使用,但是在学习过程中发现一个问题,那就是页面加载数据时,原始代码会闪现一下.查访各方资料,终的解决方法. 第一步.加入一段css代码 <style type="text/css"> [v-cloak] { display: none; } </style> 第二步.在view上引用css模块 <div id="app" v-cloak> <h1>{{message}}</h1>

  • vue.js input框之间赋值方法

    如下所示: demo.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index Page</title> </head> <body> <form action="" id="demo"> <input type="text" va

  • vue组件之间数据传递的方法实例分析

    本文实例分析了vue组件之间数据传递的方法.分享给大家供大家参考,具体如下: 1.props:父组件 -->传值到子组件 app.vue是父组件 ,其它组件是子组件,把父组件值传递给子组件需要使用 =>props 在父组件(App.vue)定义一个属性(变量)sexVal = '男'  把该值传递给 子组件(B.vue),如下: App.vue <template> <div id="app"> <!--<router-view>&

  • Vue深入讲解数据响应式原理

    目录 响应式是什么 如何实现数据响应式 实现对象属性拦截 通用的劫持方案 总结 响应式是什么 简而言之就是数据变页面变 如何实现数据响应式 在Javascript里实现数据响应式一般有俩种方案,分别对应着vue2.x 和 vue3.x使用的方式,他们分别是: 对象属性拦截 (vue2.x) Object.defineProperty 对象整体代理 (vue3.x) Proxy 其中对象属性拦截,道理都是相通的 实现对象属性拦截 字面量对象定义 let data = { name:'小兰同学' }

  • 使用Vue.js实现数据的双向绑定

    目录 如何用Vue.js实现数据的双向绑定? 1. 理解双向绑定 2. 使用v-model指令 3. 使用自定义组件实现双向绑定 4. 数据劫持 5. 模板引擎 6.Object.defineProperty()详解 如何用Vue.js实现数据的双向绑定? 在Vue.js中,双向数据绑定是一项非常强大的功能,它能够使数据和视图之间保持同步,让开发者更加方便地操作数据.在本文中,我们将介绍如何用Vue.js实现数据的双向绑定. 1. 理解双向绑定 首先,我们需要了解双向绑定的原理.在Vue.js中

  • 利用vue.js插入dom节点的方法

    本文主要介绍的是vue.js插入dom节点的方法,下面话不多说,来看看详细的介绍吧. html代码: <div id="app"></div> js代码: var MyComponent = Vue.extend({ template: '<div>Hello World</div>' }) var myAppendTo = Vue.extend({ template:'<p>appendTo</p>' }) va

随机推荐