Vue 2和Vue 3的响应式原理对比

特点 Vue 2 Vue 3
响应式系统 使用 Object.defineProperty 进行数据劫持 使用 Proxy 对象进行数据劫持
响应式数据变化检测 基于 getter/setter 实现 基于 Proxy 对象实现
对嵌套对象和数组的处理 需要特殊的处理方式,不够直观 更好地支持对嵌套对象和数组的响应式处理
性能 在大型数据集上可能存在性能问题 在某些情况下比 Vue 2 更好地优化了性能

在 Vue 2 中,响应式系统是通过使用 Object.defineProperty 来进行数据劫持,利用 getter 和 setter 来监听数据的变化。然而,这种方式在处理嵌套对象和数组时需要特殊的处理方式,不够直观,并且在大型数据集上可能存在性能问题。

相比之下,在 Vue 3 中采用了 Proxy 对象代替了 Object.defineProperty,这样可以更自然、高效地处理嵌套对象和数组的变化。另外,由于 Proxy 对象的引入,Vue 3 在某些情况下对大型数据集的性能优化也更好。因此,从响应式原理的角度来看,Vue 3 相比 Vue 2 有一些显著的改进。

Vue生命周期和每个阶段的特点

Vue2 生命周期 DOM DATA 生命周期作用
beforeCreate 在实例初始化之后,数据观测 (data observer) 和事件配置 (event watcher) 之前被调用。
created 完成了数据观测和事件配置,未挂载到 DOM 上。可以访问 data 中的数据,进行一些初始话操作。
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted 实例已经挂载到 DOM 上,可以访问页面中的元素,进行 DOM 操作等。
beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁后被调用。
beforeUnmount 实例从页面中销毁之前调用,可以在这个钩子中进行一些清理工作。
unmounted 实例从页面中销毁后调用。
Vue 3 DOM DATA 生命周期作用
onBeforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
onMounted 实例已经挂载到 DOM 上,可以访问页面中的元素,进行 DOM 操作等。
onBeforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
onUpdated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁后被调用。
onBeforeUnmount 实例从页面中销毁之前调用,可以在这个钩子中进行一些清理工作。
onUnmounted 实例从页面中销毁后调用。

在 Vue 3 中,生命周期钩子名称前都带有”on”前缀,并且包括了onBeforeMountonMounted钩子。另外还引入了onBeforeUnmountonUnmounted钩子,以替代beforeDestroydestroyed钩子,从而更准确地描述组件销毁过程。Options API 和 Composition API 带来了一些不同之处,特别是在数据管理和组件逻辑方面。因此,在使用不同 API 时,可能会对应不同的生命周期处理方式。

Vue和JavaScript中常用的设计模式

1. 观察者模式(Observer Pattern)

  • Vue 中的应用:Vue.js 中的响应式系统就是基于观察者模式实现的。当数据变化时,所有依赖于该数据的地方都会得到通知并进行相应的更新。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Vue中的观察者模式示例
    const vm = new Vue({
    data: {
    message: "Hello",
    },
    });

    vm.$watch("message", function (newVal, oldVal) {
    console.log(`message从${oldVal}变为${newVal}`);
    });

    vm.message = "Hello, Vue";

2. 发布-订阅模式(Pub/Sub Pattern)

  • Vue 中的应用:Vue.js 的事件机制使用了发布-订阅模式。组件可以通过$emit来发布事件,而通过$on来订阅事件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Vue中的发布-订阅模式示例
    const eventBus = new Vue();

    // 订阅事件
    eventBus.$on("sayHello", function () {
    console.log("Hello from eventBus");
    });

    // 发布事件
    eventBus.$emit("sayHello");

3. 单例模式(Singleton Pattern)

  • JavaScript 中的应用:单例模式确保类只有一个实例,并提供一个全局访问点。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // JavaScript中的单例模式示例
    const Singleton = (function () {
    let instance;

    function createInstance() {
    return {
    name: "I am a singleton object",
    };
    }

    return {
    getInstance: function () {
    if (!instance) {
    instance = createInstance();
    }
    return instance;
    },
    };
    })();

    const instance1 = Singleton.getInstance();
    const instance2 = Singleton.getInstance();

    console.log(instance1 === instance2); // 输出 true

4. 工厂模式(Factory Pattern)

  • JavaScript 中的应用:工厂模式用于创建对象,隐藏具体的创建逻辑,并提供统一的接口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // JavaScript中的工厂模式示例
    function Car(options) {
    this.brand = options.brand || "Unknown Brand";
    this.model = options.model || "Unknown Model";
    }

    function CarFactory() {}
    CarFactory.prototype.createCar = function (options) {
    return new Car(options);
    };

    const factory = new CarFactory();
    const myCar = factory.createCar({ brand: "Toyota", model: "Camry" });

设计模式在 Vue 和 JavaScript 中有着广泛的应用,能够帮助开发人员更好地组织代码结构、降低耦合度以及提高代码复用性。对于不同的场景和需求,选择合适的设计模式能够让代码更加健壮和可维护。

JavaScript中的数组遍历方法详解

在JavaScript中,有多种方法可以用来遍历数组。下面是一些常见的数组遍历方法:

  1. for循环:

    1
    2
    3
    4
    let arr = [1, 2, 3, 4, 5];
    for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
    }
  2. forEach()方法:

    1
    2
    3
    arr.forEach(function(item) {
    console.log(item);
    });
  3. map()方法:

    1
    2
    3
    let newArr = arr.map(function(item) {
    return item * 2;
    });
  4. for…of循环:

    1
    2
    3
    for (let item of arr) {
    console.log(item);
    }
  5. for…in循环(不推荐用于数组遍历):

    1
    2
    3
    for (let index in arr) {
    console.log(arr[index]);
    }
  6. filter()方法:

    1
    2
    3
    let filteredArr = arr.filter(function(item) {
    return item > 2;
    });
  7. reduce()方法:

    1
    2
    3
    let sum = arr.reduce(function(accumulator, currentValue) {
    return accumulator + currentValue;
    }, 0);

这些方法各自有其特点和适用场景。开发者可以根据实际情况选择合适的方法进行数组遍历和操作。

块级格式化上下文BFC

BFC(Block Formatting Context)是指块级格式化上下文,它是页面中的一块独立的渲染区域,内部元素的布局不会影响到外部元素。BFC 具有如下特性:

  1. 内部的盒子会在垂直方向一个接一个地放置。
  2. 垂直方向上的边距会发生折叠。
  3. BFC 的区域不会与浮动盒子重叠。
  4. BFC 是页面上一个独立的容器,容器内部的布局不会影响到外部元素。

应用场景:

  • 清除浮动:当父元素包含了浮动的子元素时,可以触发父元素的 BFC 特性来清除浮动,避免父元素高度塌陷的问题。
  • 避免边距重叠:当需要避免相邻块级元素的垂直边距重叠时,可以创建 BFC 来限制边距的传播。
  • 多栏布局:利用 BFC 可以实现多栏布局,其中每个列就是一个 BFC 区域,避免了多栏布局中的一些问题。

通过理解 BFC 的概念和应用场景,前端开发人员可以更好地处理布局方面的问题,并优化页面的渲染效果。