当前位置: 首页 > Web前端 > vue.js

2、3代Vue响应系统比上一波强,前一波死了吗?(下篇)

时间:2023-03-31 14:30:12 vue.js

转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,为开发者赋能。原文参考:https://www.sitepoint.com/vue...响应式系统是现代前端框架的关键部分之一。应用系统的高交互性、动态性和响应性的能力都由它支撑。每个网络开发人员都应该了解这个系统的功能和实际操作。原理响应系统是一种自动保持数据源(模型)和数据表示(视图)层同步的机制。每次模型更改时,都会重新渲染视图。以一个简单的Markdown编辑器为例。通常编辑器有两个面板:一个面板用于编写Markdown代码(用于修改基础模型),另一个面板用于预览编译后的HTML(显示更新的视图)。当我们在书写面板中书写内容时,它会立即在预览面板中自动预览。这个例子比较简单,但实际上会复杂很多。在很多情况下,我们要显示的数据依赖于其他数据。在这种情况下,需要根据跟踪更新相关数据。例如,我们有一个由firstName和lastName属性组成的fullName。当修改其任何依赖项时,将自动重新评估fullName,并将结果显示在视图中。现在我们知道了什么是反应式系统,让我们快速回顾一下Vue2中的反应式系统及其注意事项,然后再了解它在Vue3中的工作原理以及如何在实践中使用它。引入Vue2的反应式系统响应性在Vue2中或多或少是“隐藏”的。无论我们在数据对象中放入什么,Vue都会使其隐式响应。虽然这可以使开发人员的工作更加轻松,但灵活性不可避免地会降低。在幕后,Vue2使用ES5Object.defineProperty将数据对象的所有属性转换为getter和setter。对于每个组件实例,Vue创建一个依赖观察器实例,观察器记录组件渲染期间依赖项收集/跟踪的任何属性。当属性触发依赖项的setter时,观察者会收到通知,组件会重新呈现,视图也会更新。但是也会出现一些问题。更改检测警告由于Object.defineProperty方法的限制,Vue无法检测到某些数据更改。包括:向对象添加属性或从对象中删除属性(例如obj.newKey=value)通过索引设置数组项(例如arr[index]=newValue)修改数组的长度(例如arr.length=newLength)但是为了为了解决这些问题,Vue提供了Vue.set的API方法,为response对象添加一个属性,保证新的属性也是响应式的,从而触发视图更新。用下面描述实例讨论该情况:

你好!我的名字是{{person.name}}。我{{person.age}}岁。

添加“年龄”属性

这是我最喜欢的活动:

    {{item}}编辑
清除活动列表
el:'#app',data:{person:{name:"David"},activities:["Readingbooks","Listeningmusic","WatchingTV"]},methods:{//1.为对象添加一个新属性addAgeProperty(){this.person.age=30},//2.通过索引设置数组项editActivity(index){constnewValue=prompt('Inputanewvalue')if(newValue){this.activities[index]=newValue}},//3.修改数组的长度clearActivities(){this.activities.length=0}}});在上面的例子中,我们会发现这三种方法都不行,不能添加新的属性,不能使用activities的索引来编辑数组中的item,也不能修改activities数组的长度。优化如下:el:'#app',data:{person:{name:"David"},activities:["Readingbooks","Listeningmusic","WatchingTV"]},methods:{//1.给对象添加一个新的属性addAgeProperty(){Vue.set(this.person,'age',30)},//2.通过索引设置一个数组项editActivity(index){constnewValue=prompt('Inputanewvalue')if(newValue){Vue.set(this.activities,index,newValue)}},//3.修改数组的长度clearActivities(){this.activities.splice(0)}}});在此示例中,我们使用Vue.setAPI方法向person对象添加一个新的age属性,并从活动数组中选择/修改特定项目。在最后一种情况下,使用JavaScript内置的splice方法。这种做法是完全可行的,但略显笨拙,而且会导致代码不一致。而Vue3解决了这个问题。让我们继续下面的例子:data(){return{person:{name:"David"},activities:["Readingbooks","Listeningmusic","WatchingTV"]}},methods:{//1.AddinganewpropertytotheobjectaddAgeProperty(){this.person.age=30},//2.通过索引设置数组项editActivity(index){constnewValue=prompt('Inputanewvalue')if(newValue){this.activities[index]=newValue}},//3.修改数组长度clearActivities(){this.activities.length=0}}}Vue.createApp(App).mount('#app')正如您在Vue3中看到的那样,所有方法都可以正常工作。在Vue2.6中,引入的Vue.observableAPI方法在一定程度上暴露了响应式系统,让开发者可以体验到响应式系统的内容。事实上,这与Vue内部使用的包装数据对象的方法完全相同,这对于在简单场景中创建小型跨组件状态存储很有用。但是还是没法和Vue3的响应式系统比,接下来就详细介绍一下。注意:由于Object.defineProperty方法是ES5-only且不可调整大小的特性,Vue2不支持IE8及以下版本。Vue3反应系统如何工作Vue3中的反应系统已经完全重写,以充分利用ES6代理和反射API。新版本增加了响应式API,使系统比以前更加灵活和强大。ProxyAPI允许开发人员拦截和修改对目标对象的低级对象操作。代理是对象的克隆/包装器,并提供特殊功能(称为目标)来响应特定操作并覆盖JavaScript对象的内置行为(称为陷阱)。如果还需要使用默认行为,可以使用对应的ReflectionAPI,其名称顾名思义就是反映了ProxyAPI的方法。下面是如何在Vue3中使用这些API的示例:name:"David",age:27};consthandler={get(target,property,receiver){//track(target,property)console.log(property)//输出:namereturnReflect.get(target,property,receiver)},set(target,property,value,receiver){//trigger(target,property)console.log(`${property}:${value}`)//输出:“年龄:30”和“爱好:编程”returnReflect.set(目标、属性、值、接收者)}}letproxy=newProxy(person,handler);console.log(person)//get(读取属性值)console.log(proxy.name)//output:David//set(写入属性)proxy.age=30;//set(创建一个新的property)proxy.hobby="编程";console.log(person)要创建新代理,请使用新的Proxy(target,handler)构造函数。它有两个参数:目标对象(person对象)和handler对象,它定义了将拦截哪些操作(get和set操作)。在处理程序对象中,获取和设置陷阱以跟踪何时读取属性以及何时修改/添加属性。设置控制台语句以确保正常运行。get和settrap中使用了以下参数:target:被代理包裹的目标对象property:属性名value:属性值(该参数仅用于设置操作)receiver:要操作的对象(通常aproxy)ReflectAPI方法及其相应的代理方法接受相同的参数跟踪函数和特定于Vue的触发器函数,用于跟踪何时读取属性以及何时修改/添加属性。在示例的最后一部分,控制台语句用于输出原始人物对象。然后用另外一条语句读取属性名的代理对象。接下来,修改年龄属性并创建一个新的爱好属性。最后,再次输出对象,看它是否正确更新。以上就是Vue3响应式系统的完整工作流程,但是在实际工作中会复杂很多。使用Vue3响应式系统,有一些注意事项:只适用于支持ES6的浏览器+Response代理不等于原始对象总结以上我们对比了Vue2和Vue3中的响应式系统部分,对比了响应式系统的工作原理被解释。在后续文章中,我们将进一步介绍Vue3中响应式系统的API,敬请期待。延伸阅读如果你已经精通Vue3,让我们通过实际搭建一个基于Vue3组件的表格编辑系统来学习更深入