Vue2和Vue3的双向数据绑定原理

简介: Vue2和Vue3的双向数据绑定原理

前言:

今天小编给大家讲解一下,Vue2和Vue3的双向数据绑定原理。

我正在参加 2022年「博客之星」年度总评选,请大家帮我支持一下,给我一个五星。

|

点击前往我的评选页面:

|803fcf374c764e9999ceca87e0a13297.png

大家只要按图给我五星即可,谢谢大家的帮助。


vue2.x 是如何实现响应式系统的:


当你把一个普通的 js 对象传入 vue 实例作为 data 选项,vue 将遍历此对象的所有prototype(属性),并使用 object.defineProperty(),将这些 prototype(属性),全部转换为 getter / setter,在 getter 中收集数据依赖,在 setter 中监听数据变化,一旦数据发生改变,在通知订阅者。


每个组件实例,都对应一个 watcher 实例,它会在组件渲染的过程把 “接触” 过的数据 prototype(属性)记录为依赖,之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染;


defineProperty 的痛点:


  1. 它无法发现对象新增和被删除的属性,当你给一个对象添加一个新的属性,这个新增的属性没有添加到 vue 的数据更新侦查机制里;
  2. Vue.set() 可以让 vue 知道你新增了一个属性,其实 Vue.set 可以让 Vue 知道新增了一个属性。其实 set() 内部也是通过调用 defineProperty() 来实现;


当你利用索引直接设置一个数组(new Array(4))或者修改数组的长度时,Vue 不能检测到数组的变动;

当对象嵌套的层数特别深(多层嵌套)的时候,递归遍历带来的性能开销就会比较大;


Object.defineProperty 代码的使用

mounted() {
    // 先定义好一套规则
    class Observer {
      constructor(data) {
        for (let key of Object.keys(data)) {
          if (typeof data[key] === "object") {
            data[key] = new Observer(data[key]);
          }
          Object.defineProperty(this, key, {
            enumerable: true,
            configurable: true,
            get() {
              console.log("You visited" + key);
              return data[key];
            },
            set(NewValue) {
              console.log("You set" + key);
              console.log("New Value" + NewValue);
              if (NewValue === data[key]) {
                return;
              }
              data[key] = NewValue;
            },
          });
        }
      }
    }
    let obj = {
      name: "app",
      age: 18,
      a: {
        b: 1,
        c: {
          d: 1,
        },
      },
    };
    let app = new Observer(obj);
    console.log(app);
    app.age = 20;
    app.newProperty = "new attrs";
    console.log(app);
  },

715a1b20424e42dc98ed1724f16bb8d2.png

Proxy 方法的理解

Proxy 在 vue3.0 中上位


可以解决 defineProperty 的痛点,因为本质的原因在于 Proxy 是内置了拦截器对象。所有的外部访问都得先经过这一层拦截,不管是先前定义好的,还是新增的属性,又或者是深层的嵌套属性,访问时都会被拦截;


Reflect.set()方法用于设置对象属性的值,1:目标对象:2:改变参数的名称:3:改变参数的值:4:值是this如果遇到设置器,将提供给目标调用。

此方法返回一个布尔值,该值指示该属性是否已成功设置。


Proxy 代码的使用:

mounted() {
    const obj = {
      name: "app",
      age: 19,
      a: {
        b: 1,
        c: 2,
      },
    };
    const p = new Proxy(obj, {
      get(target, propKey, receiver) {
        console.log("Your visited:" + propKey);
        // Reflect.set()方法用于设置对象属性的值:1:目标对象:2:改变参数的名称:3:改变参数的值
        // 此方法返回一个布尔值,该值指示该属性是否已成功设置。
        return Reflect.set(target, propKey, receiver);
      },
      set(target, propKey, value, receiver) {
        console.log("You set:" + propKey);
        console.log("New value:" + value);
        // Reflect.set()方法用于设置对象属性的值,1:目标对象:2:改变参数的名称:3:改变参数的值:4:值是this如果遇到设置器,将提供给目标调用。
        // 此方法返回一个布尔值,该值指示该属性是否已成功设置。
        return Reflect.set(target, propKey, value, receiver);
      },
    });
    p.age = "20";
    console.log(p);
    p.newProperty = "New attribute";
    console.log(p);
  },

结果:

9767281f673445b7bbb18a8dbe7becbf.png

总结:

  1. proxy 是用来操作对象并且扩展对象能到,而 Object.defineProperty() 只是单纯的操作对象的属性;

Vue2.X 是用 Object.defineProperty() 实现数据响应的,但是受限于 defineProperty() 的实现,必须递归遍历至对象的最底层;

vue3.0 用 Proxy 来拦截对象,不管对目标执行任何操作,都会先通过 Proxy 的处理逻辑;

除了 Vue3.0,还有其他的库也在使用 Proxy。

最后还请大家帮我点击一下,谢谢大家的帮助

我正在参加 2022年「博客之星」年度总评选,请大家帮我支持一下,给我一个五星。

|

点击前往我的评选页面:

803fcf374c764e9999ceca87e0a13297.png


大家只要按图给我五星即可,谢谢大家的帮助。


以上就是 Vue2和Vue3的双向数据绑定原理,不懂得也可以在评论区里问我或私聊我询问,以后会持续发布一些新的功能,敬请关注。

相关文章
|
6天前
|
缓存 监控 UED
升级 Vue3 时,如何减少打包体积的增加?
升级 Vue3 时,如何减少打包体积的增加?
86 59
|
6天前
|
JavaScript
在vue3中(vite)引入unocss,安装配置unocss
在vue3中(vite)引入unocss,安装配置unocss
|
6天前
|
API UED
升级 Vue3 后,项目的打包体积会有什么变化?
升级 Vue3 后,项目的打包体积会有什么变化?
93 57
|
7天前
|
缓存 JavaScript 前端开发
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
该文章全面覆盖了Vue.js从基础知识到进阶原理的48个核心知识点,包括Vue CLI项目结构、组件生命周期、响应式原理、Composition API的使用等内容,并针对Vue 2与Vue 3的不同特性进行了详细对比与讲解。
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
|
6天前
|
API UED
如何实现Vue2项目升级Vue3?
如何实现Vue2项目升级Vue3?
14 1
|
8天前
|
JavaScript 前端开发 API
vue3的传送门teleport究竟有多神奇?suspense发起异步请求有多简约?
该文章介绍了Vue3中新特性Teleport和Suspense的使用方法,演示了如何使用Teleport进行DOM节点的非父子关系传送,以及Suspense在处理异步组件加载时的优雅展示和错误处理技巧。
|
8天前
|
JavaScript
particles 粒子背景插件在vue3中的使用
本文介绍了如何在Vue 3项目中使用`particles.vue3`库来创建粒子背景特效。文章提供了粒子背景插件的概述、安装步骤、配置参数说明,并展示了粒子特效的实现效果。同时,提供了在main.js中进行全局配置、在Vue组件中使用粒子背景组件的示例代码,以及完整代码的下载链接。
|
8天前
|
JavaScript API
再不学vue3就没有人要你了!速来围观vue3
这篇技术文章介绍了作者从最初对学习 Vue3 抵触到最终决定投入学习的心路历程,展示了 Vue3 相较于 Vue2 的诸多改进和新特性,如更优的性能、更小的代码体积及更佳的 TypeScript 支持。文章重点阐述了 Vue3 中 createApp 的使用变化、emits 机制、多事件处理、Fragment 的引入等重要功能升级。此外,还深入探讨了 Composition API 和 Options API 的区别,强调 Composition API 在代码组织和逻辑复用方面的优势,并给出了在不同项目规模中选择合适 API 的建议。
20 0
|
8天前
|
JavaScript 前端开发 UED
组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList
该文章详细介绍了如何使用Vue3结合TypeScript来开发全局Header组件和列表数据渲染组件ColumnList,并提供了从设计到实现的完整步骤指导。
|
8天前
|
JavaScript API
模块化妙用!用vue3实现一个鼠标追踪器和异步加载组件
该文章展示了如何使用Vue3的Composition API实现鼠标追踪器功能,并介绍了创建异步加载组件的方法,利用TS泛型增强了组件的灵活性与可维护性。