前端Vue篇之双向数据绑定的原理、使用 Object.defineProperty() 来进行数据劫持有什么缺点?

本文主要是介绍前端Vue篇之双向数据绑定的原理、使用 Object.defineProperty() 来进行数据劫持有什么缺点?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 双向数据绑定的原理
    • 数据劫持
    • 模板解析
    • 订阅者
    • MVVM整合
  • 使用 Object.defineProperty() 来进行数据劫持有什么缺点?


双向数据绑定的原理

双向数据绑定是一种数据驱动的编程模式,它将视图层和数据模型层进行了双向绑定,当数据模型层的数据发生变化时,视图层的数据也会随之更新,反之亦然。

在前端框架中,双向数据绑定的实现原理通常是通过数据劫持和发布/订阅模式来实现的。当数据模型层的数据发生变化时,会触发一个更新视图的操作,这个操作会通知所有订阅了这个数据的视图进行更新。反之,当视图层的数据发生变化时,也会触发一个更新数据模型的操作,这个操作会通知所有订阅了这个数据的数据模型进行更新。

这样,无论是数据模型层的数据发生变化,还是视图层的数据发生变化,都会自动地更新另一层的数据,实现了数据模型层和视图层的双向绑定。

在Vue.js中,双向数据绑定的原理基于数据劫持结合发布者-订阅者模式。以下是详细的步骤:

  1. 数据劫持:首先,需要对要观察(observe)的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter。这样给这个对象的某个值赋值就会触发 setter,从而能够监听到数据变化。

  2. 模板解析:在编译(compile)阶段,Vue.js会解析模板指令,将模板中的变量替换成数据,并初始化渲染页面视图。每个指令对应的节点都会被绑定更新函数,同时添加监听数据的订阅者。一旦数据有变动,收到通知后会更新视图。

  3. 订阅者:Watcher作为订阅者是Observer和Compile之间通信的桥梁。它的主要作用包括:① 在自身实例化时往属性订阅器(dep)里面添加自己; ② 必须有一个 update() 方法; ③ 待属性变动时,能调用自身的 update() 方法,并触发 Compile 中绑定的回调。

  4. MVVM整合:MVVM作为数据绑定的入口,整合了Observer、Compile和Watcher三者。通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令。最终利用Watcher搭起Observer和Compile之间的通信桥梁,实现数据变化时的视图更新以及视图交互变化时的数据 model 变更,实现双向绑定效果。

总体来说,双向数据绑定机制允许视图层和数据层之间的同步更新。在 Vue 和其他类似框架中,双向数据绑定的实现原理通常基于初始化、视图监听器、数据监听器和反向更新这些步骤,形成一个闭环,确保数据模型和视图之间的双向同步。

数据劫持

数据劫持是一种编程技术,用于在数据被读取或修改时执行一些额外的操作。在JavaScript中,数据劫持通常通过使用Object.definePropertyProxy对象来实现。

例如,我们可以使用Object.defineProperty来劫持一个对象的属性:

let obj = { name: 'Alice' };Object.defineProperty(obj, 'name', {get: function() {console.log('Name has been read');return this._name;},set: function(value) {console.log('Name has been set');this._name = value;}
});obj.name = 'Bob'; // 输出: "Name has been set"
console.log(obj.name); // 输出: "Name has been read", "Bob"

在这个例子中,我们劫持了obj对象的name属性,当name属性被读取或设置时,会执行我们定义的getset方法。

数据劫持在实现双向数据绑定和响应式系统时非常有用,因为它允许我们在数据被读取或修改时执行一些额外的操作,例如更新视图或触发事件。

在Vue.js中,数据劫持是通过使用Object.definePropertyProxy对象来实现的。Vue.js使用数据劫持来实现其响应式系统,这是Vue.js实现双向数据绑定的关键。

当你在Vue.js中创建一个数据对象时,Vue.js会遍历这个对象的所有属性,使用Object.definePropertyProxy对象来劫持这些属性。当这些属性被读取或修改时,Vue.js会执行一些额外的操作,例如更新视图或触发事件。

例如,当你在Vue.js中创建一个数据对象时:

let vm = new Vue({data: {name: 'Alice'}
});

Vue.js会劫持vm对象的name属性,当name属性被读取或修改时,Vue.js会执行一些额外的操作。

这样,无论是数据模型层的数据发生变化,还是视图层的数据发生变化,都会自动地更新另一层的数据,实现了数据模型层和视图层的双向绑定。

模板解析

在Vue.js中,模板解析是指将Vue.js的模板语法解析为JavaScript代码的过程。Vue.js的模板语法允许你在HTML模板中使用JavaScript表达式,指令和插值,这些都需要在运行时被解析为JavaScript代码。

例如,当你在Vue.js的模板中使用插值({{ }})时,这个插值会被解析为一个JavaScript表达式:

<div id="app">{{ message }}
</div>

在这个例子中,{{ message }}会被解析为_v(_s(message)),其中_v是一个函数,用于创建一个文本节点,_s是一个函数,用于转义特殊字符。

模板解析是Vue.js实现其响应式系统的关键,因为它允许你在模板中使用JavaScript表达式,指令和插值,这些都需要在运行时被解析为JavaScript代码。

订阅者

在Vue.js中,订阅者是指那些订阅了数据变化的对象。当数据发生变化时,订阅者会被通知,然后它们可以执行一些操作,例如更新视图。

在Vue.js的响应式系统中,订阅者通常是指那些使用了数据劫持的对象。当一个属性被劫持后,Vue.js会为这个属性创建一个订阅者列表,然后当这个属性的值发生变化时,Vue.js会遍历这个订阅者列表,通知所有的订阅者。

例如,当你在Vue.js中创建一个数据对象时:

let vm = new Vue({data: {name: 'Alice'}
});

Vue.js会为vm对象的name属性创建一个订阅者列表,然后当name属性的值发生变化时,Vue.js会遍历这个订阅者列表,通知所有的订阅者。

MVVM整合

MVVM是Model-View-ViewModel的缩写,是一种软件架构模式,它将应用程序分为三个部分:模型(Model)、视图(View)和视图模型(ViewModel)。在MVVM中,视图模型是视图和模型之间的中介,它负责处理视图的显示逻辑和用户输入,同时也负责从模型中获取数据。

在Vue.js中,MVVM是通过Vue实例来实现的。Vue实例是一个MVVM模式的实现,它将模板(View)和数据(Model)绑定在一起,同时也提供了一些方法和属性来处理视图的显示逻辑和用户输入(ViewModel)。

例如,当你在Vue.js中创建一个Vue实例时:

let vm = new Vue({el: '#app',data: {message: 'Hello Vue.js!'}
});

这个Vue实例就是一个MVVM模式的实现。它将模板(View)和数据(Model)绑定在一起,同时也提供了一些方法和属性来处理视图的显示逻辑和用户输入(ViewModel)。

总的来说,MVVM是一种非常强大的软件架构模式,它可以帮助你更好地组织和管理你的代码,同时也可以提高你的代码的可维护性和可测试性。

使用 Object.defineProperty() 来进行数据劫持有什么缺点?

使用 Object.defineProperty() 进行数据劫持存在以下一些缺点:

  1. 无法监听数组的变化Object.defineProperty() 只能劫持对象的属性,对于数组,它无法直接监听数组内部元素的变化,例如通过索引修改数组元素的值或者使用 push、pop 等方法改变数组长度。

  2. 初始遍历开销大:在初始化时,需要递归遍历所有的属性并使用 Object.defineProperty() 进行劫持,这会导致初始遍历的开销较大。

  3. 只能监听属性的变化Object.defineProperty() 只能劫持对象的属性,无法劫持整个对象的变化。如果要深度监听对象,需要遍历对象的每个属性进行劫持。

  4. 兼容性问题:在一些旧版本的浏览器中,Object.defineProperty() 的兼容性可能存在问题,限制了其在某些环境下的应用。

因为上述缺点,Vue 在新版本中采用了更高效的数据劫持方式,例如使用 ES6 中的 Proxy 对象来代替 Object.defineProperty(),以解决这些问题。Proxy 对象可以更灵活地监听对象的操作,并且能够监听数组的变化,提高了数据劫持的效率和功能性。在 Vue 3.0 中已经不再使用 Object.defineProperty() 这种方式,而是通过使用 Proxy 对象进行代理,从而实现数据劫持。 Proxy 能够完美监听到任何方式的数据改变,但唯一的缺点是兼容性的问题,因为 Proxy 是 ES6 的语法。

持续学习总结记录中,回顾一下上面的内容:
双向数据绑定的原理就是通过数据劫持和模板解析来实现的。这样无论是数据模型的数据发生变化,还是视图的数据发生变化,都会自动地更新另一层的数据。使用 Object.defineProperty() 进行数据劫持的主要缺点是它只能劫持对象的属性,而不能劫持对象本身或数组的变化。这意味着如果你想劫持一个对象或数组,你需要为它的每个属性或元素都添加一个 getter 和 setter,这会导致代码变得复杂和难以维护。

这篇关于前端Vue篇之双向数据绑定的原理、使用 Object.defineProperty() 来进行数据劫持有什么缺点?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/714069

相关文章

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

使用TomCat,service输出台出现乱码的解决

《使用TomCat,service输出台出现乱码的解决》本文介绍了解决Tomcat服务输出台中文乱码问题的两种方法,第一种方法是修改`logging.properties`文件中的`prefix`和`... 目录使用TomCat,service输出台出现乱码问题1解决方案问题2解决方案总结使用TomCat,

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫