前端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

相关文章

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

prometheus如何使用pushgateway监控网路丢包

《prometheus如何使用pushgateway监控网路丢包》:本文主要介绍prometheus如何使用pushgateway监控网路丢包问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录监控网路丢包脚本数据图表总结监控网路丢包脚本[root@gtcq-gt-monitor-prome

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件