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

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H