帝国手机网站cms系统,一般做网站上传的图片大小,江西赣州公司,展示产品的网站 个人备案还是企业目录
1.Vue3 响应式原理
一、 响应式的基本概念
二、 核心机制#xff1a;Proxy 和依赖追踪
三、 触发更新的过程
四、 代码示例
五、 优势总结
2.如何实现组件间通信#xff1f;
一、父子组件通信
1. 父传子#xff1a;Props 传递
2. 子传父#xff1a;自定义事…目录
1.Vue3 响应式原理
一、 响应式的基本概念
二、 核心机制Proxy 和依赖追踪
三、 触发更新的过程
四、 代码示例
五、 优势总结
2.如何实现组件间通信
一、父子组件通信
1. 父传子Props 传递
2. 子传父自定义事件
二、兄弟组件通信
1. 通过共同父组件中转
2. 事件总线Event Bus
三、跨层级通信
1. Provide/Inject依赖注入
2. 全局状态管理Vuex/Pinia
四、特殊场景方案
1.$refs 直接访问慎用
2.$attrs/$listeners透传特性
五、通信方式对比
六、实际案例参考
3.Composition 的生命周期钩子
一、主要生命周期钩子函数
1.onBeforeMount()
2.onMounted()
3.onBeforeUpdate()
4.onUpdated()
5.onBeforeUnmount()
6.onUnmounted()
7.onErrorCaptured()
二、使用注意事项
三、代码示例
4.Composition API vs Options API
一、Options API选项式 API
1. 特点
2. 示例代码
3.优点
4.缺点
二、 Composition API组合式 API
1. 特点
2. 示例代码
3. 优点
4. 缺点
三、核心对比
四、使用场景
5.setup() 函数作用
一、 核心作用
二、关键注意事项
6.ref 和 reactive 的区别
一、基本定义
二、主要区别
三、示例
四、使用场景
7.Props 传递机制
一、基本概念
二、 在子组件中声明 Props
声明方式
Options API
Composition API
三、在父组件中传递 Props
示例
四、 Props 的类型验证和默认值
示例
五、单向数据流原则
六、高级用法
8.自定义事件 (emit)
一、在子组件中定义和触发事件
二、 在父组件中监听事件
三、注意事项
9.生命周期钩子对比
一、生命周期阶段与钩子对照表
二、关键变化说明
1.重命名的钩子
2.Composition API 特性
3.新增调试钩子
三、执行顺序对比同一组件
10.watch 和 watchEffect 的区别
一、 基本概念
二、主要区别
三、示例
四、适用场景总结
1.watch
2.watchEffect 1.Vue3 响应式原理
Vue3 的响应式原理是其核心特性之一它允许数据变化时自动更新视图。相比 Vue2Vue3 使用了 JavaScript 的 Proxy 对象来实现更高效和灵活的响应式系统。下面我将逐步解释其工作机制帮助你理解整个过程。
一、 响应式的基本概念
响应式系统确保当数据如变量或对象属性发生变化时依赖该数据的视图或计算逻辑自动更新。这类似于数学中的函数依赖关系如果 $y f(x)$那么当 $x$ 改变时$y$ 应自动重新计算。Vue3 的核心是创建一个响应式代理对象它会拦截对数据的访问get和修改set操作从而追踪依赖并触发更新。
二、 核心机制Proxy 和依赖追踪
Proxy 对象Vue3 使用 JavaScript 的 Proxy API 来包装原始数据。Proxy 可以定义“陷阱”traps如 get 和 set用于拦截操作。 当访问属性时如 obj.aget 陷阱被触发系统记录当前依赖例如一个渲染函数。当修改属性时如 obj.a 1set 陷阱被触发系统通知所有依赖进行更新。 依赖追踪Vue3 通过一个全局的“依赖收集器”来管理依赖关系。每个响应式属性都关联一个依赖集合称为 Dep当属性被访问时当前运行的“effect”函数如组件的渲染函数会被添加到这个集合中。 这可以用一个简单的数学关系表示假设有一个响应式对象 $data$其属性 $x$ 的依赖集合为 $D_x$。当 $x$ 改变时系统遍历 $D_x$ 并执行每个 effect 函数。公式表示如果 $effect \in D_x$那么 $x$ 变化时 $effect()$ 被调用。
三、 触发更新的过程
当数据被修改时Proxy 的 set 陷阱会执行以下步骤
更新原始数据值。通知依赖集合遍历所有依赖的 effect 函数并调用它们。如果 effect 函数涉及计算属性如 $computed x y$系统会重新计算这些值。
优势Proxy 支持深层嵌套对象和数组的响应式无需像 Vue2 那样递归遍历整个对象这提高了性能。
四、 代码示例
下面是一个简化版的 Vue3 响应式实现使用 JavaScript 代码演示核心逻辑。注意实际 Vue3 源码更复杂但这里聚焦基本原理。
// 创建一个响应式对象
function reactive(target) {return new Proxy(target, {get(obj, key) {track(obj, key); // 追踪依赖记录当前 effect 函数return obj[key];},set(obj, key, value) {obj[key] value;trigger(obj, key); // 触发更新通知所有依赖return true;}});
}// 依赖收集和触发函数简化版
const depsMap new Map(); // 存储每个对象的依赖映射function track(target, key) {let dep depsMap.get(target);if (!dep) {dep new Map();depsMap.set(target, dep);}let effects dep.get(key);if (!effects) {effects new Set();dep.set(key, effects);}if (currentEffect) {effects.add(currentEffect); // 添加当前 effect 到依赖集合}
}function trigger(target, key) {const dep depsMap.get(target);if (dep) {const effects dep.get(key);if (effects) {effects.forEach(effect effect()); // 执行所有依赖的 effect 函数}}
}// 定义一个 effect 函数例如组件的渲染逻辑
let currentEffect null;
function effect(fn) {currentEffect fn;fn(); // 首次执行触发依赖收集currentEffect null;
}// 使用示例
const state reactive({ count: 0 });effect(() {console.log(Count is: ${state.count}); // 依赖 state.count
});state.count 1; // 输出Count is: 1自动触发更新五、 优势总结
高效性Proxy 直接拦截操作避免了 Vue2 中递归定义 getter/setter 的开销支持动态添加属性。灵活性可以处理数组索引变化、Map/Set 等复杂数据结构。可组合性Vue3 的 reactive 和 ref API 使状态管理更模块化。数学上这类似于一个动态的依赖图每个响应式属性是一个节点依赖关系是边变化时沿边传播更新。
2.如何实现组件间通信
实现组件间通信是前端开发中的核心问题不同框架有各自的解决方案。以下是主流的通信方式及代码示例
一、父子组件通信
1. 父传子Props 传递
// 父组件
Child :messageparentData /// 子组件
export default {props: [message],mounted() {console.log(this.message) // 接收父组件数据}
}2. 子传父自定义事件
// 子组件
this.$emit(child-event, data) // 触发事件// 父组件
Child child-eventhandleEvent /methods: {handleEvent(data) {console.log(data) // 接收子组件数据}
}二、兄弟组件通信
1. 通过共同父组件中转
// 父组件
ChildA sendreceiveData /
ChildB :datasharedData /data() {return { sharedData: null }
},
methods: {receiveData(data) {this.sharedData data // 中转数据}
}2. 事件总线Event Bus
// 创建事件中心
const bus new Vue()// 组件A发送
bus.$emit(update, data)// 组件B接收
bus.$on(update, data {console.log(data)
})三、跨层级通信
1. Provide/Inject依赖注入
// 祖先组件
provide() {return { theme: dark }
}// 后代组件任意层级
inject: [theme],
mounted() {console.log(this.theme) // 输出 dark
}2. 全局状态管理Vuex/Pinia
// store.js
export default new Vuex.Store({state: { count: 0 },mutations: {increment(state) {state.count}}
})// 任意组件
this.$store.commit(increment)
console.log(this.$store.state.count)四、特殊场景方案
1.$refs 直接访问慎用
Child refchildComp /methods: {callChild() {this.$refs.childComp.childMethod()}
}2.$attrs/$listeners透传特性
// 父组件
Child :titlepageTitle closehandleClose /// 中间组件
Grandchild v-bind$attrs v-on$listeners /五、通信方式对比
方式适用场景优点缺点Props/Events父子组件简单直接层级深时繁琐Event Bus任意组件解耦灵活难以追踪事件源Vuex/Pinia中大型应用集中管理调试工具完善增加项目复杂度Provide/Inject深层嵌套组件避免逐层传递数据非响应式需处理 最佳实践建议 优先使用 Props/Events 处理父子通信跨层级使用 Provide/Inject 替代多级 Props复杂应用采用 Vuex/Pinia 管理全局状态避免过度使用 $refs 和事件总线防止代码混乱 六、实际案例参考
// 使用Pinia状态管理
// store/counter.js
export const useCounterStore defineStore(counter, {state: () ({ count: 0 }),actions: {increment() {this.count}}
})// 组件A
import { useCounterStore } from /store/counter
const store useCounterStore()
store.increment() // 组件B
const store useCounterStore()
console.log(store.count) // 实时获取最新值3.Composition 的生命周期钩子
在 Vue.js 的 Composition API 中生命周期钩子提供了一种在组件不同阶段如创建、更新、销毁执行自定义逻辑的方式。与 Options API 不同Composition API 使用函数式钩子如 onMounted、onUnmounted这些钩子需要在 setup() 函数或 script setup 语法中导入和使用。下面我将逐步解释主要钩子及其用法。
一、主要生命周期钩子函数
Composition API 提供了以下核心钩子每个钩子对应组件生命周期的特定阶段
1.onBeforeMount()
用途在组件挂载到 DOM 之前调用。适合执行初始化操作如设置状态或获取数据。触发时机在 setup() 函数运行后组件首次渲染前。
2.onMounted()
用途在组件挂载到 DOM 后调用。常用于访问 DOM 元素、发起 API 请求或设置事件监听器。触发时机组件首次渲染完成。
3.onBeforeUpdate()
用途在组件更新之前调用。适合在状态变化前执行清理或验证逻辑。触发时机响应式数据变化后DOM 更新前。
4.onUpdated()
用途在组件更新后调用。用于处理更新后的 DOM 操作或状态同步。触发时机DOM 重新渲染完成后。
5.onBeforeUnmount()
用途在组件卸载之前调用。适合执行清理工作如移除事件监听器或取消定时器。触发时机组件销毁流程开始前。
6.onUnmounted()
用途在组件卸载后调用。用于最终资源释放如断开网络连接或清除缓存。触发时机组件从 DOM 中移除后。
7.onErrorCaptured()
用途捕获子组件或当前组件的错误。用于错误处理或日志记录。触发时机组件树中任何地方抛出错误时。
二、使用注意事项
执行顺序钩子按生命周期顺序执行例如onBeforeMount → onMounted → onBeforeUpdate → onUpdated → onBeforeUnmount → onUnmounted。依赖导入所有钩子需从 vue 包导入并在 setup() 函数内调用。异步支持钩子回调可以是异步函数适用于数据获取等操作。性能优化避免在频繁更新的钩子如 onUpdated中执行重操作以防止性能问题。
三、代码示例
以下是一个简单的 Vue 3 组件示例展示如何使用 Composition API 的生命周期钩子
templatediv{{ message }}/div
/templatescript
import { ref, onMounted, onUnmounted } from vue;export default {setup() {const message ref(组件加载中...);// 挂载后更新消息onMounted(() {message.value 组件已挂载;console.log(DOM 已渲染);});// 卸载时清理资源onUnmounted(() {console.log(组件已卸载);});return { message };}
};
/script4.Composition API vs Options API
在 Vue.js 开发中Composition API 和 Options API 是两种不同的组件代码组织方式。以下是它们的核心区别和适用场景分析 一、Options API选项式 API
1. 特点
通过预设选项如 data, methods, computed组织代码逻辑分散在不同选项中相同功能可能跨多个选项适合简单场景学习曲线平缓
2. 示例代码
export default {data() {return { count: 0 }},methods: {increment() {this.count}},computed: {doubleCount() {return this.count * 2}}
}3.优点
结构清晰直观适合新手选项隔离降低耦合度兼容性好Vue 2/3 均支持
4.缺点
复杂组件中逻辑碎片化代码复用依赖 mixins易命名冲突 二、 Composition API组合式 API
1. 特点
通过 setup() 函数集中管理逻辑基于函数组合如 ref, reactive, computed逻辑按功能聚合而非选项类型
2. 示例代码
import { ref, computed } from vueexport default {setup() {const count ref(0)const doubleCount computed(() count.value * 2)function increment() {count.value}return { count, doubleCount, increment }}
}3. 优点
逻辑高内聚复杂组件更易维护更好的 TypeScript 支持灵活的逻辑复用自定义 Hook代码更精简减少 this 依赖
4. 缺点
学习曲线较陡峭需理解响应式原理过度集中可能降低可读性 三、核心对比
维度Options APIComposition API代码组织按选项类型分散按功能逻辑集中逻辑复用Mixins易冲突自定义 Hook解耦性强TS 支持有限完整类型推断适用场景简单组件/新手项目复杂逻辑/大型应用响应式数据通过 data() 返回通过 ref()/reactive() 声明 四、使用场景
Options API 项目简单或团队 Vue 经验较少需要快速迭代原型维护旧版 Vue 2 项目
Composition API组件逻辑复杂如状态管理、异步流程),需要高度复用逻辑自定义 Hook,使用 TypeScript 开发,长期维护的大型项目
5.setup() 函数作用
一、 核心作用
setup()函数主要用于初始化程序环境包括设置变量初始值、配置硬件参数、定义画布大小等。它只在程序执行时调用一次之后不再运行
二、关键注意事项
执行时机setup()只在程序启动时运行一次必要性在支持setup()的框架中它是必须定义的函数即使为空否则程序可能报错常见错误如果在setup()外部放置初始化代码可能导致未定义行为或性能问题
6.ref 和 reactive 的区别
一、基本定义
ref: 用于创建一个响应式引用适用于基本类型如数字、字符串、布尔值或对象。它返回一个带有 .value 属性的对象访问或修改数据需要通过 .value。reactive: 用于创建一个响应式对象适用于对象或数组。它直接返回一个代理对象属性可以直接访问和修改无需额外语法。
二、主要区别
方面refreactive适用类型更适合基本类型如 number, string也可用于对象。仅适用于对象或数组不适用于基本类型。访问方式必须通过 .value 访问或修改数据例如 myRef.value。直接访问属性例如 myReactive.key无需 .value。模板使用在模板中自动解包无需写 .valueVue 内部处理。在模板中直接使用属性名行为更直观。内部实现包装一个值使用 Object.defineProperty 或 Proxy 实现响应式。基于 Proxy 代理整个对象深度监听嵌套属性。解构问题解构后仍保留响应性因为返回的是引用对象。解构对象会丢失响应性需使用 toRefs 辅助函数保持。重新赋值可以重新赋值整个对象通过 myRef.value newValue。不能直接重新赋值整个对象需修改属性或使用 Object.assign。
三、示例
import { ref, reactive } from vue;// 使用 ref 示例
const countRef ref(0); // 基本类型
console.log(countRef.value); // 输出: 0
countRef.value 10; // 修改值const userRef ref({ name: Alice, age: 30 }); // 对象类型
console.log(userRef.value.name); // 输出: Alice// 使用 reactive 示例
const userReactive reactive({ name: Bob, age: 25 }); // 对象类型
console.log(userReactive.name); // 输出: Bob无需 .value
userReactive.age 26; // 直接修改属性// 解构问题演示
const { age } userReactive; // 解构会丢失响应性
// 正确方式使用 toRefs 保持响应性
const { name, age: reactiveAge } toRefs(userReactive);四、使用场景
ref:处理基本类型数据需要频繁重新赋值整个对象
reactive 处理复杂对象或嵌套数据结构,需要直接访问属性避免写 .value 的模板代码
总结
用 reactive 管理状态对象用 ref 处理独立的基本值选择时考虑数据结构和代码可读性简单值用 ref复杂对象用 reactive。
7.Props 传递机制
一、基本概念
Props 允许父组件将数据“注入”到子组件中子组件通过声明 Props 来接收这些数据。数据流是单向的父组件更新 Props 会触发子组件重新渲染但子组件不能直接修改 Props用途适用于配置子组件、传递静态或动态数据例如传递用户信息、配置选项等。
二、 在子组件中声明 Props
子组件需要显式声明它可以接收的 Props。这通常在组件的选项或 Composition API 中完成。 声明方式 使用 props 选项Options API或 defineProps 宏Composition API。每个 Prop 可以指定类型、默认值和验证规则。 Options API // 子组件 (ChildComponent.vue)
export default {props: {// 基本类型声明例如字符串title: String,// 带默认值的数字类型count: {type: Number,default: 0},// 必填的布尔类型isActive: {type: Boolean,required: true}}
}Composition API // 子组件 (ChildComponent.vue)
import { defineProps } from vueconst props defineProps({title: String,count: { type: Number, default: 0 },isActive: { type: Boolean, required: true }
})三、在父组件中传递 Props
静态传递直接传递固定值。动态传递绑定到父组件的数据或计算属性实现响应式更新。
示例
!-- 父组件模板 --
templateChildComponenttitle欢迎使用 Vue 3 !-- 静态字符串 --:countparentCount !-- 动态绑定数字 --:is-activeisActive !-- 动态绑定布尔值 --/
/templatescript
import ChildComponent from ./ChildComponent.vueexport default {components: { ChildComponent },data() {return {parentCount: 10, // 父组件数据isActive: true}}
}
/script四、 Props 的类型验证和默认值
类型可以指定为原生类型如 String, Number, Boolean, Array, Object或自定义类型。默认值通过 default 属性设置当父组件未传递 Prop 时使用。验证使用 validator 函数进行自定义验证
示例
props: {age: {type: Number,default: 18,validator: (value) value 0 // 验证年龄非负}
}五、单向数据流原则
Props 是只读的子组件不能直接修改接收到的 Prop。如果需要基于 Prop 派生数据应使用计算属性。原因确保数据源单一避免父子组件间的循环更新。 // 子组件中错误做法直接修改 Prop
// this.count 20 // 不允许会触发警告// 正确做法使用计算属性或本地数据
computed: {doubledCount() {return this.count * 2 // 基于 Prop 派生新值}
}六、高级用法
传递对象或数组使用 v-bind 传递整个对象子组件通过 Prop 接收。 !-- 父组件 --
ChildComponent :user-info{ name: 张三, age: 30 } /Prop 命名约定建议使用 camelCase 声明但在模板中使用 kebab-caseHTML 属性不区分大小写。例如声明为 userInfo传递时用 user-info。响应式更新父组件数据变化时子组件的 Prop 会自动更新得益于 Vue 的响应式系统。
8.自定义事件 (emit)
一、在子组件中定义和触发事件
使用 defineEmits 声明事件列表。在方法中调用 emit 函数触发事件并传递数据。在模板中绑定事件触发器如按钮点击。
//子组件 ChildComponent.vue
script setup
// 导入 defineEmits
import { defineEmits } from vue;// 定义事件列表声明一个名为 customEvent 的事件
const emit defineEmits([customEvent]);// 定义一个方法在触发时发送事件
function handleClick() {// 触发 customEvent 事件并传递数据例如字符串 Hello from child!emit(customEvent, Hello from child!);
}
/scripttemplate!-- 在按钮点击时调用 handleClick 方法 --button clickhandleClick触发自定义事件/button
/template二、 在父组件中监听事件
导入子组件。在模板中使用 event-name 或 v-on:event-name 监听事件。定义一个回调函数来处理事件数据。
//父组件 ParentComponent.vue
script setup
// 导入子组件
import ChildComponent from ./ChildComponent.vue;// 定义回调函数接收子组件传递的数据
function onCustomEvent(data) {console.log(事件触发数据:, data); // 输出事件触发数据: Hello from child!// 这里可以添加业务逻辑例如更新父组件状态
}
/scripttemplate!-- 监听子组件的 customEvent 事件并绑定回调函数 --ChildComponent customEventonCustomEvent /
/template三、注意事项
事件命名规范推荐使用 kebab-case短横线分隔命名事件如 custom-event以保持与 HTML 属性一致。在模板中监听时使用 custom-event但在 defineEmits 中声明时使用 camelCase如 customEvent。数据传递emit 可以传递多个参数例如 emit(event, arg1, arg2)父组件回调函数接收这些参数。TypeScript 支持如果使用 TypeScript可以通过泛型定义事件类型 script setup langts
const emit defineEmits{(event: customEvent, data: string): void;
}();
/script错误处理确保事件名一致避免拼写错误。如果父组件未监听事件子组件的 emit 不会报错但也不会执行任何操作。替代方案对于简单场景也可以使用 Props 传递数据但自定义事件更适合子组件主动通知父组件的场景。
9.生命周期钩子对比
Vue 3 的生命周期钩子在 Options API 和 Composition API 中有不同实现方式同时部分钩子名称与 Vue 2 有差异。以下是核心对比
一、生命周期阶段与钩子对照表
阶段Vue 2 (Options)Vue 3 (Options API)Vue 3 (Composition API)初始化beforeCreatebeforeCreate无逻辑在 setup() 内createdcreated无逻辑在 setup() 内挂载前beforeMountbeforeMountonBeforeMount挂载完成mountedmountedonMounted更新前beforeUpdatebeforeUpdateonBeforeUpdate更新完成updatedupdatedonUpdated卸载前beforeDestroybeforeUnmountonBeforeUnmount卸载完成destroyedunmountedonUnmounted缓存组件activatedactivatedonActivateddeactivateddeactivatedonDeactivated错误捕获errorCapturederrorCapturedonErrorCaptured调试钩子无无onRenderTrackedonRenderTriggered
二、关键变化说明
1.重命名的钩子
beforeDestroy → beforeUnmount更准确描述组件卸载行为destroyed → unmounted语义更清晰
2.Composition API 特性
所有钩子以 onXxx 形式导入如 onMountedbeforeCreate 和 created 被 setup() 替代 import { onMounted } from vue;export default {setup() {// 替代 created 逻辑console.log(初始化逻辑);onMounted(() {console.log(组件已挂载);});}
}3.新增调试钩子
onRenderTracked追踪响应式依赖onRenderTriggered诊断重新渲染原因 三、执行顺序对比同一组件
Options API: beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeUnmount → unmountedComposition API:setup() → onBeforeMount → onMounted → onBeforeUpdate → onUpdated → onBeforeUnmount → onUnmounted最佳实践建议 新项目优先使用 Composition API逻辑更聚合迁移项目可逐步替换重命名钩子如 beforeDestroy → beforeUnmount调试响应式问题时使用 onRenderTracked/onRenderTriggered 10.watch 和 watchEffect 的区别
一、 基本概念
watch: 用于显式观察一个或多个响应式数据源如 ref、reactive 对象、函数等并在其变化时执行回调函数。它允许你指定依赖项并控制监听行为如深度监听或立即执行。watchEffect: 自动跟踪其函数体内部的响应式依赖项并在任何依赖变化时重新运行该函数。它类似于计算属性computed但用于执行副作用如 DOM 操作、API 调用而非返回一个值。
二、主要区别
特性watchwatchEffect依赖项指定方式需要显式声明依赖源如 () data.value。自动收集函数体中的所有响应式依赖项。初始执行行为默认不立即执行回调可通过 { immediate: true } 选项启用。在创建时立即执行一次函数体。访问旧值/新值回调函数可接收旧值和新值作为参数如 (newVal, oldVal) {}。无法直接访问旧值只提供当前值。深度监听支持支持 { deep: true } 选项进行深度监听如对象嵌套属性。默认深度监听所有依赖项无需额外选项。适用场景适合精确控制监听逻辑如当特定数据变化时触发操作。适合自动响应依赖变化如执行副作用或初始化任务。停止监听通过返回的停止函数手动停止如 const stop watch(...); stop()。同样通过返回的停止函数手动停止。
三、示例
import { ref, reactive, watch, watchEffect } from vue;export default {setup() {const count ref(0);const user reactive({ name: Alice, age: 25 });// 示例 1: 使用 watchwatch(// 显式指定依赖源count 和 user.name[() count.value, () user.name],// 回调函数接收新值和旧值([newCount, newName], [oldCount, oldName]) {console.log(watch - count 变化:, newCount, 旧值:, oldCount);console.log(watch - name 变化:, newName, 旧值:, oldName);},// 选项立即执行和深度监听{ immediate: true, deep: true });// 示例 2: 使用 watchEffectwatchEffect(() {// 自动跟踪 count.value 和 user.ageconsole.log(watchEffect - count:, count.value);console.log(watchEffect - age:, user.age);// 注意这里无法访问旧值});// 修改数据以触发监听setTimeout(() {count.value 1; // 触发 watch 和 watchEffectuser.name Bob; // 触发 watchuser.age 26; // 触发 watchEffect}, 1000);return { count, user };}
};四、适用场景总结
1.watch
你需要精确控制监听哪些数据源。需要访问变化前后的值如比较旧值和新值。场景示例表单验证当特定字段变化时检查、API 请求当 ID 变化时重新获取数据。
2.watchEffect
依赖项复杂或动态希望自动跟踪所有响应式引用。需要立即执行副作用如初始化日志或设置事件监听器。场景示例实时日志输出、自动清理资源结合 onInvalidate 函数。 如果依赖项明确且需要旧值用 watch如果依赖项动态或需要简化代码用 watchEffect。