记录2

61 阅读5分钟

Vue2 vs Vue3 区别

Composition API vs Options API:

Vue2:主要使用 Options API(data、methods、computed 等),代码组织按选项分块,逻辑分散。

Vue3:引入 Composition API(setup 函数或

  • 性能优化
    • Vue3:使用 Proxy 实现响应式,性能更优(后文详细讲解)。
    • Vue3:静态节点标记(Static Hoisting)、事件监听缓存,减少重新渲染开销。
    • Vue3:打包体积更小,通过 Tree-Shaking 移除未使用的代码。
  • 新特性
    • Vue3:支持 Fragments(多根节点组件)、Teleport(传送门)、Suspense(异步组件加载)。
    • Vue3:更好的 TypeScript 支持,API 更友好。
    • Vue3:移除了一些 Vue2 的 API,如 onon、off、setset、delete。
  • 响应式系统
    • Vue2:基于 Object.defineProperty,有局限性。
    • Vue3:基于 Proxy,支持动态添加属性、数组操作等(后文详细讲解)。
  • 构建工具
    • Vue2:依赖 Webpack 或其他打包工具。

    • Vue3:推荐 Vite,构建速度更快。

问:为什么 Vue3 引入 Composition API? 答:Options API 在大型项目中逻辑分散,难以维护。Composition API 允许按功能组织代码,复用性更强(如 use 函数),并支持更好的 TypeScript 类型推导。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 Vue2 生命周期

  • 钩子

    • beforeCreate:组件创建前,data 和 methods 未初始化。
    • created:data 和 methods 已初始化,但 DOM 未挂载。
    • beforeMount:DOM 渲染前。
    • mounted:DOM 渲染完成。
    • beforeUpdate:数据更新前。
    • updated:数据更新后,DOM 重新渲染完成。
    • beforeDestroy:组件销毁前。
    • destroyed:组件销毁后。
  • 基本钩子名称不变,但 beforeDestroy 改为 beforeUnmount,destroyed 改为 unmounted,更符合组件卸载的语义。

  • Composition API 中使用 onXxx 函数(如 onMounted、onUnmounted)替代 Options API 的钩子。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

diff

核心思想

  • 同层比较:只比较同一层级的节点,不跨层比较。

  • key 的作用:通过 key 标识节点,优化列表更新效率。

  • 最小量更新:尽量复用现有 DOM 节点,只更新变化的部分。

  • 新旧 VNode 比较:检查是否为相同节点(sameVnode:标签相同、key 相同)。

  • 复用或更新

    • 如果是相同节点,递归比较子节点(patch)。

    • 如果不同,直接替换整个节点树。

:为什么需要 key?

  • :key 帮助 Vue 识别节点,减少 DOM 操作,提高 diff 效率。没有 key,Vue 会按顺序比较,可能导致不必要的更新。

:Vue3 的 diff 算法如何优化?

  • :Vue3 通过静态标记跳过不变节点,优化列表比较算法(如最长递增子序列),减少 DOM 操作,提高性能。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

<input v-model="message" />
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value" />

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

:为什么 React 推荐函数组件?

  • :函数组件更简洁,易于测试和维护;Hooks 提供灵活的状态和副作用管理;避免 this 绑定问题;支持更好的代码复用。

useState

  • 作用:管理函数组件的状态,提供状态变量和更新函数。
  • 用法:const [state, setState] = useState(initialState);
    • state:当前状态值。

    • setState:更新状态的函数,支持直接值或函数式更新。

useEffect

  • 作用:处理副作用(如数据获取、订阅、DOM 操作),模拟类组件的生命周期。
  • 用法:useEffect(() => { ... }, [dependencies]);
    • 第一个参数:副作用函数。
    • 第二个参数:依赖数组,控制副作用执行时机。
    • 可返回清理函数,在组件卸载或依赖变化时执行。

useEffect 如何模拟生命周期?

  • :空依赖数组模拟 componentDidMount;依赖数组变化模拟 componentDidUpdate;返回清理函数模拟 componentWillUnmount。

diff 过程

  1. 根节点比较:检查节点类型和属性是否变化。
  2. 子节点比较
    • 列表节点:使用 key 进行高效匹配,比较顺序、增删、更新。

    • 非列表节点:递归比较子节点。

useEffect 是 React 的一个 Hook,用于在函数组件中处理副作用(side effects),如数据获取、订阅、DOM 操作、定时器等。

useEffect(() => {
  // 副作用逻辑
  return () => {
    // 清理逻辑(可选)
  };
}, [dependencies]);
  • 第一个参数:副作用函数,包含需要执行的副作用逻辑。

  • 第二个参数:依赖数组,控制副作用的执行时机。

  • 返回值(可选):清理函数,在组件卸载或依赖变化前执行。

执行时机

  • 组件渲染完成后执行副作用。

  • 依赖数组变化时,重新执行副作用(先运行清理函数,再运行新副作用)。

  • 组件卸载时,运行清理函数。

依赖数组的作用

  • 控制 useEffect 的执行频率。

  • 空数组([]):仅在组件挂载和卸载时执行。

  • 无依赖数组:每次渲染后都执行。

  • 指定依赖(如 [count]):仅在依赖变化时执行。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

父组件 -> 子组件

  • 方式:通过 props 传递数据或函数。

  • 场景:父组件向子组件传递状态、配置或回调函数。

    // 父组件 import React, { useState } from 'react'; import Child from './Child';

    function Parent() { const [message, setMessage] = useState('Hello from Parent'); const handleChildClick = (childData) => { console.log('Received from child:', childData); };

    return ; }

    // 子组件 function Child({ message, onChildClick }) { return (

    {message}

    <button onClick={() => onChildClick('Hello from Child')}> Send to Parent
    ); }

子组件 -> 父组件

  • 方式:子组件通过调用父组件传递的回调函数(props 中的函数)通知父组件。
  • 场景:子组件触发事件(如点击、输入),更新父组件状态。
  • 代码示例(见上例):
    • 子组件调用 onChildClick 向父组件传递数据。

:兄弟组件通信为何不直接传递数据?

  • :React 遵循单向数据流,兄弟组件无法直接通信,需通过父组件或 Context/State 管理工具作为中介。

  • 父子组件通信

    • 父 -> 子:通过 props 传递数据或函数。
    • 子 -> 父:通过回调函数通知父组件更新。
  • 兄弟组件通信

    • 通过父组件共享状态。
    • 使用 Context 或状态管理工具(如 Zustand)简化通信。
  • 跨层级组件通信

    • 使用 Context 提供全局状态,适合简单场景。

    • 使用状态管理库(如 Redux、Zustand)处理复杂状态。

  • 状态是组件内部的数据,适合局部逻辑(如表单输入、计数器)。

  • 全局状态是状态的扩展,解决跨组件或跨层级的数据共享问题。

  • 全局变量是定义在全局作用域(如 window 或 global)的普通 JavaScript 变量,可被任何代码访问。无响应式:变化不会触发视图更新,需手动操作 DOM。