百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Vue2和Vue3数据双向绑定原理的区别及优缺点

ztj100 2025-03-24 01:38 11 浏览 0 评论

我们都知道,Vue 是一套用于构建用户界面的渐进式框架,是目前前端领域主流框架之一,作为前端框架,它有两大核心:

1.数据双向绑定:当数据发生改变,视图可以自动更新,可以不用关心dom操作,而专心数据操作;

2.可组合的视图组件:把视图按照功能切分成若干基本单元,组件可以一级一级组合整个应用形成倒置组件树,可维护,可重用,可测试。

Vue从之前的1版本到现在基本所有公司都用到的2版本经历了一次重大变革,到2020年10月5日,Vue3的源码正式发布。3版本的发布其中比较变化大的一个点就是Vue的数据双向绑定的原理发生了变化,那么我们知道,数据双向绑定的原理在前端的面试中基本上是必问的,可见其重要性。那么接下来我们着重讨论一下Vue2和Vue3版本的数据双向绑定原理的区别及其各自的优缺点。

由于本篇篇幅较长,咱们本次先讨论Vue2的数据双向绑定原理,Vue3的数据双向绑定原理咱们在下篇再做介绍。

一、什么是MVVM模式

在讨论Vue的数据双向绑定原理之前,我们还得知道咱们平时工作中用Vue开发的开发模式是什么,那就是MVVM模式。

大多数的开发模式,可能通过最多的是MVC开发模式,当然还有更多的MVP模式,发布订阅者模式等等,那么Vue为什么要采用MVVM的开发模式,其实主要还是因为MVVM模式可以实现数据的双向绑定,它是如何实现的?

MVVM可以分为,模型层,视图层,视图模型层,模型层主要干的事情就是负责与业务数据相关的操作,就像我们data函数中返回的数据一样,主要负责数据方面的工作,view层顾名思义就是主要负责视图相对应的操作,神秘的vm层也就是视图模型层主要是干什么的?视图模型层就类似一座桥梁,链接模型(数据层)和视图层,它的工作是双向的一边监听数据一边观测试图,无论是数据层发生变化还是视图层发生变化,他都会同步给对方,让视图层和数据层保持一致。实现数据的双向绑定。

通过下面这张图可以看到他们三者之间的一个工作流程:

MVVM框架模式图

二、Vue2数据双向绑定原理的实现

Vue2采用数据劫持并结合发布者-订阅者模式的方式,通过ES6的object.defineProperty()方法去劫持各个属性的setter/getter方法,在数据发生变化的时候,发布消息给订阅者,触发相应的监听回调。

具体步骤如下:

1、需要observe(观察者)的数据对象进行遍历,包括子属性对象的属性,都加上setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据的变化。

2、compile(解析)解析模版指令,将模版中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。

3、watcher(订阅者)是observer和compile之间通信的桥梁,主要做的事情是:

Ⅰ、在实例化时往属性订阅器(dep)里添加自己;

Ⅱ、自身必须有一个update()方法;

Ⅲ、待属性变动dep.notice()通知时,能够调用自身的update()方法,并触发compile中绑定的回调。

4、MVVM作为数据绑定入口,整合observer,compile和watcher来监听自己的model数据变化,通过compile来解析编译模版,最终利用watcher搭起observer和compile之间的通信桥梁,达到数据变化->更新视图:视图交互变化->数据model变更的双向绑定效果。

结合上面所说可以看下面这张图,能有个直观的感受:

Vue2数据双向绑定原理图

三、源码剖析

那么Vue2的源码是如何具体实现它的数据双向绑定原理的呢?我们对源码进行剖析,发现它的代码实现步骤如下:

1. observer实现对vue各个属性进行监听

function defineReactive( obj, key, val ) {

// 每个属性建立个依赖收集对象,get中收集依赖,set中触发依赖,调用更新函数

var dep = new Dep();

Object.defineProperty(obj, key, {

enumerable: true,

configurable: true,

get: function() {

// 收集依赖 Dep.target标志

Dep.target && dep.addSub(Dep.target)

return val

},

set: function(newVal){

if(newVal === val) return

// 触发依赖

dep.notify()

val = newVal

}

})

}

2. dep实现

function Dep(){

this.subs = []

}

Dep.prototype = {

constructor: Dep,

addSub: function(sub){

this.subs.push(sub)

},

notify: function(){

this.subs.forEach(function(sub){

sub.update() // 调用的Watcher的update方法

})

}

}

3. compiler实现对各个指令模板的解析器

通过compiler实现对vue各个指令模板的解析器,生成抽象语法树,编译成Virtual Dom,渲染视图。

// 编译器

function compiler(node, vm){

var reg = /\{\{(.*)\}\}/;

// 节点类型为元素

if(node.nodeType ===1){

var attr = node.attributes;

// 解析属性

for(var i=0; i< attr.length;i++){

if(attr[i].nodeName == 'v-model'){

var _value = attr[i].nodeValue

node.addEventListener('input', function(e){

//给相应的data属性赋值,触发修改属性的setter

vm[_value] = e.target.value

})

node.value = vm[_value] // 将data的值赋值给node

node.removeAttribute('v-model')

}

}

new Watcher(vm,node,_value,'input')

}

// 节点类型为text

if(node.nodeType ===3){

if(reg.test(node.nodeValue)){

var name = RegExp.$1;

name = name.trim()

new Watcher(vm,node,name,'input')

}

}

}

4.Watcher连接observer和compiler

通过他们之间的连接,接受每个属性变动的通知,绑定更新函数,更新视图。

function Watcher(vm,node,name, nodeType){

Dep.target = this; // this为watcher实例

this.name = name

this.node = node

this.vm = vm

this.nodeType = nodeType

this.update() // 绑定更新函数

Dep.target = null //绑定完后注销 标志

}

Watcher.prototype = {

get: function(){

this.value = this.vm[this.name] //触发observer中的getter监听

},

update: function(){

this.get()

if(this.nodeType == 'text'){

this.node.nodeValue = this.value

}

if(this.nodeType == 'input') {

this.node.value = this.value

}

}

}

总结

以上就是关于Vue2的数据双向绑定原理的刨析,如果你仔细阅读了,相信一定会让你有所收获,接下来咱们会在下篇中讨论Vue3的数据双向绑定原理,这里咱们先做个思考:是不是新版的数据双向绑定原理就优于旧版的?可以给大家提前透露一下,并不是这样的,两者各有优缺点。

相关推荐

30天学会Python编程:16. Python常用标准库使用教程

16.1collections模块16.1.1高级数据结构16.1.2示例...

强烈推荐!Python 这个宝藏库 re 正则匹配

Python的re模块(RegularExpression正则表达式)提供各种正则表达式的匹配操作。...

Python爬虫中正则表达式的用法,只讲如何应用,不讲原理

Python爬虫:正则的用法(非原理)。大家好,这节课给大家讲正则的实际用法,不讲原理,通俗易懂的讲如何用正则抓取内容。·导入re库,这里是需要从html这段字符串中提取出中间的那几个文字。实例一个对...

Python数据分析实战-正则提取文本的URL网址和邮箱(源码和效果)

实现功能:Python数据分析实战-利用正则表达式提取文本中的URL网址和邮箱...

python爬虫教程之爬取当当网 Top 500 本五星好评书籍

我们使用requests和re来写一个爬虫作为一个爱看书的你(说的跟真的似的)怎么能发现好书呢?所以我们爬取当当网的前500本好五星评书籍怎么样?ok接下来就是学习python的正确姿...

深入理解re模块:Python中的正则表达式神器解析

在Python中,"re"是一个强大的模块,用于处理正则表达式(regularexpressions)。正则表达式是一种强大的文本模式匹配工具,用于在字符串中查找、替换或提取特定模式...

如何使用正则表达式和 Python 匹配不以模式开头的字符串

需要在Python中使用正则表达式来匹配不以给定模式开头的字符串吗?如果是这样,你可以使用下面的语法来查找所有的字符串,除了那些不以https开始的字符串。r"^(?!https).*&...

先Mark后用!8分钟读懂 Python 性能优化

从本文总结了Python开发时,遇到的性能优化问题的定位和解决。概述:性能优化的原则——优化需要优化的部分。性能优化的一般步骤:首先,让你的程序跑起来结果一切正常。然后,运行这个结果正常的代码,看看它...

Python“三步”即可爬取,毋庸置疑

声明:本实例仅供学习,切忌遵守robots协议,请不要使用多线程等方式频繁访问网站。#第一步导入模块importreimportrequests#第二步获取你想爬取的网页地址,发送请求,获取网页内...

简单学Python——re库(正则表达式)2(split、findall、和sub)

1、split():分割字符串,返回列表语法:re.split('分隔符','目标字符串')例如:importrere.split(',','...

Lavazza拉瓦萨再度牵手上海大师赛

阅读此文前,麻烦您点击一下“关注”,方便您进行讨论和分享。Lavazza拉瓦萨再度牵手上海大师赛标题:2024上海大师赛:网球与咖啡的浪漫邂逅在2024年的上海劳力士大师赛上,拉瓦萨咖啡再次成为官...

ArkUI-X构建Android平台AAR及使用

本教程主要讲述如何利用ArkUI-XSDK完成AndroidAAR开发,实现基于ArkTS的声明式开发范式在android平台显示。包括:1.跨平台Library工程开发介绍...

Deepseek写歌详细教程(怎样用deepseek写歌功能)

以下为结合DeepSeek及相关工具实现AI写歌的详细教程,涵盖作词、作曲、演唱全流程:一、核心流程三步法1.AI生成歌词-打开DeepSeek(网页/APP/API),使用结构化提示词生成歌词:...

“AI说唱解说影视”走红,“零基础入行”靠谱吗?本报记者实测

“手里翻找冻鱼,精心的布局;老漠却不言语,脸上带笑意……”《狂飙》剧情被写成歌词,再配上“科目三”背景音乐的演唱,这段1分钟30秒的视频受到了无数网友的点赞。最近一段时间随着AI技术的发展,说唱解说影...

AI音乐制作神器揭秘!3款工具让你秒变高手

在音乐创作的领域里,每个人都有一颗想要成为大师的心。但是面对复杂的乐理知识和繁复的制作过程,许多人的热情被一点点消磨。...

取消回复欢迎 发表评论: