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

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

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

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

接下来我们先讨论Vue2和Vue3版本的数据双向绑定原理的区别其各自的优缺点。

由于本篇长较长,咋们次先讨论Vue2的数据双向数据绑定原理,Vue3的数据双向数据绑定咋们在最下面聊:

一、什么是MVVM模式?

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

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

MVVM可以分为:模型层、视图层、视图模型层,模型层主要干的事情就是负责与业务数据相关的操作,就像我们data函数中返回的数据一样,主要负责数据方面的工作,view层顾名思义就是主要负责试图相对应的操作,神秘的vm层也就是视图模型层主要是是什么的?

视图模型层就是类似一座桥梁,连接模型(数据层) 和视图层,它的工作是双向的一边监听数据,一边观测试图,无论是数据层发生变化还是视图层发生变化,他都会同步给对方,让视图层和数据层保持一致。实现数据的双向绑定。

View -> ViewModel -> Model 互顺的

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

具体步骤如下:

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

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

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

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

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

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

4.MVVM作为数据绑定入口:

observer,compile和watcher来监听自己的model数据变化,通过compile来解析模板,最终利用watcher搭起observer和compile之间的通信桥梁,达成数据变化-》更新视图:视图交互变化-》数据model变更的双向绑定效果。

三、源码分析:

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

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

js 复制代码
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
        }
    })

}

二、dep的实现

js 复制代码
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,渲染视图。

js 复制代码
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

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

js 复制代码
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的底层原理分析

Vue3底层原理:

Vue3是Vue.js的最新版本,它在底层原理上进行了重大改进。Vue3的底层原理主要包括响应式系统、虚拟DOM、编辑器和渲染器等方面。

响应式系统

Vue3的响应式系统采用了Proxy代理对象来实现。Proxy是ES6中新增的一个特征,它可以拦截对象的读取、赋值、删除等操作。Vue3利用Proxy代理对象来监听数据的变化,从而实现响应式。

虚拟DOM

Vue3的虚拟DOM采用了模板编译的方式,将模板编译成渲染函数,然后再将渲染函数换成虚拟DOM。这种方式比Vue2的模板解析方式更加高效,因为模板编译只需要进行一次,而模板解析需要每次都进行。

编辑器

Vue3的编辑器采用了基于插件的架构,可以通过插件来扩展编辑器的功能。编辑器的主要作用是将模板编译成渲染函数,同时还可以进行静态优化和代码生成等操作。

Vue3的渲染器采用了基于函数的渲染器,将渲染函数转换成真实的DOM节点。这种方式比Vue2的基于类的渲染器更加高效,因为函数调用比类实例化更加快速。

总结:Vue3的底层原理采用了一系列新的技术和优化,使得Vue3在性能和扩展性方面都有了很大的提升。Vue3的响应式系统采用了Proxy代理对象,虚拟DOM采用了模板编译的方式,编辑器采用了基于插件的架构,渲染器采用了基于函数的渲染器。这些技术的应用使得Vue3成为了一个更加高效、灵活和可扩展的框架。

Vue3双向数据绑定的原理

Vue.js是一款流行的前端框架,它采用了MVVM(Model-View-ViewModel)架构模式,并实现了双向数据绑定。在Vue3中,双向数据绑定是通过Proxy对象实现的。

在Vue3中,双向数据绑定的核心是ViewModel层。ViewModel是Vue框架中的一个重要概念,它负责连接视图层和数据层。在Vue3中,Vue对象被替换为了一个Proxy对象,这个Proxy对象可以代理原始数据对象,实现对数据的劫持和监听。

Proxy对象的代理机制是通过使用get和set方法来实现的。当我们读取数据对象的属性时,Proxy会调用get方法,并返回属性的值。而当我们修改数据对象的属性时,Proxy会调用set方法,并更新属性的值。

双向数据绑定实现流程如下:

  1. 首先,我们需要创建一个数据对象,并使用Proxy对象对其进行代理。
  2. 接着,我们需要在视图中使用插值表达式或指令来绑定数据对象的属性。当视图渲染时,Vue会读取数据对象的属性,并显示在视图中。
  3. 当用户在视图中修改输入框的值时,Vue会自动检测到变化,并调用Proxy对象的set方法来更新数据对象的属性值。
  4. 当数据对象的属性值发生变化时,Vue会自动检测到变化,并重新渲染视图,从而实现双向数据绑定。

双向数据绑定的优点在于可以简化开发过程,提高开发效率。通过双向数据绑定,我们可以在视图中直接操作数据,而不需要手动更新数据。这样可以减少开发人员的工作量,并提高代码的可读性和可维护性。

然而,双向数据绑定也存在一些问题。首先,双向数据绑定会增加代码的复杂性,特别是在处理复杂的数据逻辑时。其次,双向数据绑定会带来一定的性能损耗,特别是在处理大量数据时。因此,在使用双向数据绑定时,需要合理使用,避免滥用。

总结起来,Vue3通过使用Proxy对象实现了双向数据绑定。双向数据绑定可以简化开发过程,提高开发效率。然而,双向数据绑定也存在一些问题,需要合理使用。在实际开发中,我们可以根据具体的需求来选择是否使用双向数据绑定,以达到最佳的开发效果。

相关推荐
Myli_ing1 小时前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维1 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z2 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
彭世瑜2 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4042 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish2 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five2 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序2 小时前
vue3 封装request请求
java·前端·typescript·vue