(Vue)Vue的基本原理以及Vue2和Vue3的一些不同之处

类比的解释

当你创建一个Vue实例时,就好像你建了一座"观察塔"(Vue实例),这座塔可以观察一座城市(你的数据)。这个城市中有很多房子(数据属性),每个房子都有一扇门(getter和setter),你住在这个城市的一栋房子里(Vue实例的data属性)。

  1. 遍历data属性:

    • 当你创建Vue实例时,Vue会走访这座城市,找到所有的房子(data属性)。例如,在你的城市中,有一栋名为message的房子。
  2. 使用Object.defineProperty或Proxy:

    • 对每栋房子进行加固,安装了特殊的门(使用Object.defineProperty或Proxy)。
    • 这扇门可以监听任何人进入或离开这栋房子的动作。
  3. 追踪相关依赖:

    • 在每栋房子的门上贴上一张列表(依赖列表),记录了谁来过,谁离开了。
    • 如果有人去看望message这座房子,他们会被添加到这张列表上。
  4. Watcher程序实例:

    • 城市中有一支专门的队伍(Watcher程序实例),他们会负责记录每栋房子的来访者。
    • 每栋房子都有一位专属的看守,他们会记下每个进出的人。
  5. 依赖项的setter被调用时通知Watcher:

    • 当有人来到message这座房子,如果他们改变了什么东西,就会通知这座房子的看守。
    • 通知会包括"是谁来了"和"来了之后,门上的一些变动"。
  6. 实现数据驱动视图更新:

    • 由于有了这个依赖关系和通知系统,城市的人们(你的组件)不需要一直去查看每座房子。
    • 当有人来访问message这座房子并修改了什么东西,这座房子就会通知相关的组件,说:"有人改变了我!"
    • 组件就会重新渲染,确保界面和数据保持同步。

这个"观察塔"模型帮助我们理解Vue是如何通过观察数据变化并自动更新相关视图的。Watcher程序实例就像是这座城市的"警察队",负责维护秩序并在有人违规时通知相关的人。这样,整个城市都能够自动保持有序。

基本原理

当一个Vue实例创建时,Vue会遍历data中的属性,并使用Object.defineProperty(在Vue 3.0中使用Proxy)将它们转换为getter/setter。这一步是关键,因为它使Vue能够追踪属性的访问和修改。

  1. 遍历data属性: Vue实例在创建时,会检查data对象中的所有属性。这些属性将成为Vue实例的响应式数据。
  2. 使用Object.defineProperty或Proxy: 对于每个属性,Vue会使用Object.definePropertyProxy将其转换为getter和setter。这是Vue实现响应式的核心机制之一。通过这种方式,Vue能够截获属性的读取和修改操作。
  3. 追踪相关依赖: 在getter中,Vue会追踪依赖。这意味着Vue会记录哪些组件或Watcher(观察者)正在访问这个属性。这样,当属性被修改时,Vue知道哪些地方需要进行更新。
  4. Watcher程序实例: 每个组件实例都有一个相应的Watcher程序实例。Watcher的作用是在组件渲染过程中将属性记录为依赖。Watcher会关注组件中用到的数据,一旦这些数据发生变化,Watcher就会通知组件进行重新渲染。
  5. 依赖项的setter被调用时通知Watcher: 当被追踪的属性发生变化时,其setter会被调用。这时,Vue会通知相应的Watcher,告诉它需要重新计算。这个重新计算的过程包括重新渲染组件,确保界面和数据保持同步。
  6. 实现数据驱动视图更新: 这整个过程实现了数据驱动视图的目标。当数据变化时,与之相关的组件会自动更新,而不需要手动操作DOM。这使得开发者能够更专注于数据和业务逻辑,而不必过多关注界面更新的细节。

总的来说,Vue通过数据劫持和响应式的设计,使得数据变化能够自动反映在视图上,提供了一种方便且高效的方式来构建可维护的用户界面。

相关的例子

下面将会以一个例子来介绍,希望能帮助你更好的理解 当一个Vue实例被创建时,它会检查data对象中的属性。假设我们有一个Vue组件,其中有一个叫做message的数据属性,下面是一个简单的例子:

html 复制代码
<!-- HTML 模板 -->
<div id="app">
  <p>{{ message }}</p>
</div>
js 复制代码
// JavaScript 代码
const app = new Vue({
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
});

app.$mount('#app');

现在,让我们来解释这个例子:

  1. 遍历data属性:

    • Vue创建了一个新实例,并检查data对象。
    • 在这个例子中,它找到了message属性。
  2. 使用Object.defineProperty或Proxy:

    • Vue内部使用Object.defineProperty(或在Vue 3中使用Proxy)将message属性转换为getter/setter。
  3. 追踪相关依赖:

    • 在渲染过程中,Vue的渲染引擎检测到模板中正在访问message属性。
    • 它建立了组件与message属性之间的依赖关系。
  4. Watcher程序实例:

    • Vue为该组件创建一个Watcher程序实例,该实例会在渲染过程中记录message属性作为依赖。
  5. 依赖项的setter被调用时通知Watcher:

    • 如果message属性发生变化,其setter会被调用。
    • Vue会通知与之相关的Watcher实例,告诉它需要重新计算。
  6. 实现数据驱动视图更新:

    • message属性发生变化时,与之相关的组件会自动更新,从而保持界面和数据的同步。在这个例子中,更新会导致<p>标签中的文本变为新的消息。

这个简单的过程展示了Vue是如何通过数据驱动视图更新的。

Vue2与Vue3相比

在Vue 3 中,Vue 团队进行了一些重要的改进和优化,以提高性能、可维护性和扩展性。虽然 Vue 3 仍然采用了数据驱动的核心思想,但在实现上与 Vue 2 有一些不同之处。以下是在 Vue 3 中的一些变化:

  1. Proxy 替代 Object.defineProperty: 在 Vue 3 中,Vue 引入了 Proxy 对象来替代 Vue 2 中使用的 Object.defineProperty。Proxy 提供了更强大和灵活的拦截器,使得对对象的操作更加直观和高效。
js 复制代码
// Vue 2 中使用 Object.defineProperty
const data = { count: 0 };

const vm = new Vue({
  data() {
    return { count: 0 };
  },
});

// Vue 3 中使用 Proxy
const data = new Proxy({ count: 0 }, {
  set(target, key, value) {
    console.log(`Setting ${key} to ${value}`);
    target[key] = value;
    // 触发更新
    return true;
  },
});

// 注意:Vue 3 中不再需要像 Vue 2 那样使用 data 函数
  1. Composition API: Vue 3 引入了 Composition API,这是一种基于函数的 API,使组件的逻辑更容易组织和重用。相较于 Vue 2 的选项式 API,Composition API 更灵活,使得组件的代码更加清晰。
js 复制代码
// Vue 2 的选项式 API
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment() {
      this.count++;
    },
  },
};

// Vue 3 的 Composition API
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    return { count, increment };
  },
};
  1. Reactivity API: Vue 3 中提供了新的响应式 API,以替代 Vue 2 中的 Object.defineProperty。这个新的 API 更直观、功能更强大,使得我们能够更灵活地处理响应式数据,综合来看,我个人更加喜欢Vue3的方式
js 复制代码
// Vue 2 中使用 data 函数和 reactive
const data = Vue.reactive({
  count: 0,
});

// Vue 3 中使用 ref 和 reactive
import { ref, reactive } from 'vue';

const count = ref(0);
const data = reactive({ count });
  1. Faster Mounting: Vue 3 在组件挂载性能上进行了优化,通过使用虚拟 DOM 的渲染方式以及编译器的改进,加速了组件的初始化过程。
  2. Tree-Shakable: Vue 3 被设计为更容易进行树摇(Tree-Shaking),使得在构建时能够更轻松地剔除不需要的代码,减小应用的体积。

尽管有这些变化,但核心的响应式原理,即数据驱动和依赖追踪,仍然是 Vue 3 的基石。因此,虽然细节上有所不同,但整体的响应式机制和数据驱动的思想在 Vue 3 中仍然存在。

相关推荐
sszmvb123418 分钟前
测试开发 | 电商业务性能测试: Jmeter 参数化功能实现注册登录的数据驱动
jmeter·面试·职场和发展
测试杂货铺24 分钟前
外包干了2年,快要废了。。
自动化测试·软件测试·python·功能测试·测试工具·面试·职场和发展
王佑辉25 分钟前
【redis】redis缓存和数据库保证一致性的方案
redis·面试
真忒修斯之船31 分钟前
大模型分布式训练并行技术(三)流水线并行
面试·llm·aigc
GIS程序媛—椰子43 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
木舟10091 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43911 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js