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

相关推荐
桂月二二22 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me4 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者4 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
qq_392794484 小时前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存