Vue3中的v-model、computed、watch

目录

一、v-model

二、v-bind

三、computed(计算属性)​

原理深度解析​​

​​经典使用场景​​

四、watch(侦听器)​​

​​核心作用​:​

​​原理深度解析​​

​​核心配置选项​​

​​经典使用场景​​

五、watchEffect(即时副作用)​​

​​核心作用​:​

​​原理深度解析​​

​​独特优势​​

​​经典使用场景​​


一、v-model

核心作用:​v-model 的主要功能是在​​表单输入元素​ ​或​​自定义 Vue 组件​ ​上创建​​双向数据绑定​​。它同时负责数据的读取(将 Vue 数据绑定到视图)和数据的写入(将用户输入同步回 Vue 数据)。

在原生表单元素上的实现原理:

html 复制代码
<!-- HTML 模板 -->
<input v-model="username">

等效于以下写法:

html 复制代码
<input 
  :value="username"
  @input="username = $event.target.value"
>

在自定义组件上的实现原理:

html 复制代码
<custom-input v-model="username">

等效于以下写法:

html 复制代码
<custom-input
  :model-value="username"
  @update:model-value="username = $event"
>

组件内部实现:

javascript 复制代码
// 自定义组件内部
props: ['modelValue'],
emits: ['update:modelValue'],

methods: {
  handleInput(e) {
    this.$emit('update:modelValue', e.target.value)
  }
}

二、v-bind

​核心作用:​v-bind 的核心功能是​​动态地将 Vue 实例(组件)中的数据绑定到 HTML 元素的属性(Attribute)或组件的属性(Prop)上​​。

:model ​​是 Vue 的动态属性绑定语法​​,由两部分组成:

  • 冒号' : '它是' v-bind:'的缩写
  • 属性名 model:任意自定义的属性名
  • 完整形式:v-bind:model="dataObj"

:model 不是一个内置指令或特殊属性,而是一种常见的命名约定,表示"传递整个模型对象"。

:model 的本质

  • v-bind:model 的简写形式
  • 仅用于单向数据传递(父 → 子)
  • 无内置行为,是纯属性绑定
  • 依赖开发者明确定义props接收

v-model 和 :model 的区别

​特性​ ​v-model​ ​:model​
​类型​ Vue指令 动态属性绑定
​功能​ 双向数据绑定 单向数据绑定
​实现​ 属性+事件绑定 仅属性绑定
​用途​ 表单输入组件 传递任意对象
​示例​ <input v-model="val"> <child :model="dataObj">
​组件实现​ 需要emit更新事件 仅接收props

适用场景选择

场景 推荐
​表单输入绑定​ v-model
​复杂数据传递​ :model
​组件通信​ 组合使用 :model + 自定义事件
​多个数据绑定​ 多个 v-model(如 v-model:user

三、computed(计算属性)​

**核心作用​:**​

创建​​响应式的派生数据​​,基于其他响应式数据自动计算结果并缓存

javascript 复制代码
import { computed } from 'vue'

// 基本用法
const fullName = computed(() => `${firstName.value} ${lastName.value}`)

// 可写计算属性
const writableComputed = computed({
  get() { return modelValue.value },
  set(newVal) { modelValue.value = newVal }
})

let visibleDialog = computed({
  get() {
    return props.visible;
  },
  set() {
    closeDialog();
  },
});
原理深度解析​
  1. ​惰性求值​:仅当依赖项变化时才重新计算(首次访问时也会计算)
  2. ​依赖追踪​:运行时自动追踪getter函数内访问的响应式数据
  3. ​缓存机制​:依赖项未变化时直接返回缓存结果(多次访问不重复计算)
  4. ​响应式传播​:计算属性本身就是响应式ref,改变会自动触发依赖更新
  5. ​更新时机​:在Vue的响应式更新周期中同步执行
​经典使用场景​
  • 格式化/组合数据(如 ${firstName} ${lastName}
  • 过滤/转换数据(如 todos.filter(t => !t.done)
  • 复杂数学运算(如购物车总价计算)
  • 从props派生组件内部状态(需可写计算属性)
  • 替代模板中复杂表达式(提升可读性)

computed 的自动依赖追踪原理:

​computed 会监听内部所有依赖的响应式变量值变化,自动触发重新计算并缓存结果。​

javascript 复制代码
const tipsVisible1 = computed(() => repulseForm.backToModifyType == 1);

详细过程

​依赖收集阶段​​:

  • 当首次访问 computed 属性时,Vue 会执行计算函数
  • 计算函数内部访问的每一个响应式变量(如 repulseForm.backToModifyType) 都会通过"发布-订阅"机制将这个计算函数标记为自身的一个依赖

​响应更新阶段​​:

  • 当这些被依赖的响应式变量值改变时:
    • 所有依赖它的计算函数会自动触发重新计算
    • 结果会被缓存,如果依赖没有变化则直接返回缓存值

​缓存机制​​:

  • 当多次访问 chooseNodeVisible1 时:
  • 只有当 repulseForm.backToModifyType 改变时才会重新计算
  • 否则直接返回上次计算结果

示例:

javascript 复制代码
let visibleDialog = computed({
  get() {
    return props.visible;
  },
  set() {
    closeDialog();
  },
});

​触发 getter​​:

  • 首次访问时
  • 依赖项 (props.visible) 变化后再次访问时
  • 每次在模板中渲染时

​触发 setter​​:

  • 任何赋值操作 (visibleDialog.value = ...)
  • 即使赋予的值与当前值相同
  • 通过 v-model 绑定时被调用

四、watch(侦听器)​

​**​核心作用​:**​

​显式侦听特定数据源​ ​,在变化时执行副作用(异步请求、DOM操作等)

javascript 复制代码
import { watch } from 'vue'

// 监听单一源
watch(count, (newVal, oldVal) => {
  console.log(`计数变化: ${oldVal} → ${newVal}`)
})

// 监听多个源
watch([firstName, lastName], ([newFirst, newLast]) => {
  // 处理变化...
})

// 深度监听对象
watch(
  () => ({ ...user }), 
  (newUser) => { /* 处理 */ },
  { deep: true, immediate: true }
)
​原理深度解析​
  1. ​精确依赖​:必须显式指定监听的数据源(ref、reactive、getter函数)
  2. ​变化检测​ :默认浅层比较(对象需手动开启deep:true
  3. ​回调机制​:提供新旧值对比能力
  4. ​异步执行​ :默认在组件​更新后​ 执行(通过flush选项可调整时机)
  5. ​资源回收​:自动绑定组件生命周期(卸载时自动取消监听)
​核心配置选项​
选项 作用 典型场景
deep 深度监听嵌套对象变化 表单对象监听
immediate 立即执行回调 初始数据加载
flush 控制回调执行时机 DOM操作时使用'post'
​经典使用场景​
  • 异步操作、副作用操作
  • API数据获取(搜索词变化时发起请求)
  • 路由参数监听($route.params.id变化时加载数据)
  • 表单验证(字段变化时触发验证)
  • 操作历史记录(状态变化时记录操作)

深度监听:

javascript 复制代码
watch(
  // 源获取函数:只监听user.profile对象
  () => user.profile,
  
  // 变化回调
  (newProfile) => {
    console.log("用户资料更新:", newProfile);
    // 执行相关操作
  },
  
  // 配置选项
  { deep: true } // 启用深度监听
);
javascript 复制代码
// 以下操作都会触发监听:
user.profile.name = "张三";     // 修改属性
user.profile.address.city = "北京"; // 修改嵌套属性
user.profile.hobbies.push("阅读");  // 修改数组内容
javascript 复制代码
// 如果需要新旧值对比,应创建副本:
watch(
  () => ({ ...user.profile }), // 创建浅拷贝
  (newProfile, oldProfile) => {
    // 现在可以比较具体变化
  },
  { deep: true }
);
javascript 复制代码
// watchEffect精确控制
watchEffect(() => {
  // 只追踪需要的具体属性
  if (needTracking) {
    const importantValue = someObj.deep.nested.value;
    // 使用importantValue...
  }
});

五、watchEffect(即时副作用)​

​**​核心作用​:**​

​自动追踪依赖​ ​并立即执行副作用,响应式数据变化时自动重新运行

javascript 复制代码
import { watchEffect } from 'vue'

// 基本用法
const stop = watchEffect(() => {
  document.title = `消息(${unreadCount.value})`
})

// 清理副作用
watchEffect((onCleanup) => {
  const timer = setTimeout(() => {...}, 1000)
  onCleanup(() => clearTimeout(timer))
})

// 控制执行时机
watchEffect(() => {...}, { flush: 'post' })
​原理深度解析​
  1. ​自动依赖收集​:运行时自动追踪函数内访问的所有响应式数据
  2. ​立即执行​ :首次调用时同步执行(与watch的immediate模式不同)
  3. ​智能清理​ :通过onCleanup注册清理函数(下次执行前调用)
  4. ​动态依赖​:每次执行重新收集依赖(条件分支变化时自动调整)
  5. ​执行控制​ :默认在组件​更新前​ 执行(DOM操作用flush: 'post'
​独特优势​
  • 避免手动维护依赖列表
  • 处理动态依赖(条件分支中的响应式数据)
  • 更符合命令式编程思维
  • 简化初始化逻辑(自动执行)
​经典使用场景​
  • 实时更新DOM(如标题、滚动位置)
  • 自动请求取消(onCleanup中取消请求)
  • 监听鼠标/键盘事件(自动取消注册)
  • 表单自动保存(输入变化后定时保存)
  • 日志记录(自动跟踪变化数据)

​三者的对比决策表​

特性 computed watch watchEffect
​返回类型​ 响应式ref
​执行时机​ 需要时计算 变化后回调 立即+变化时
​依赖声明​ 自动 显式声明 自动
​新旧值​ 提供
​缓存机制​
​异步支持​ ❌(纯函数)
​清理机制​ ✅(onCleanup)
​典型用途​ 派生数据 响应变化 执行副作用

**如何选择?**​

  1. 需要​推导新数据​ 吗? → computed
  2. 需要​获取变化前后值​ 吗? → watch
  3. 操作​包含异步/副作用​ 吗?
    • 依赖明确 → watch
    • 依赖动态 → watchEffect
  4. 需要​自动执行初始化​ ? → watchEffect
  5. 涉及​资源清理​ ? → watchEffect(onCleanup)

​最佳实践​ ​:优先使用computed派生数据,用watchEffect处理副作用,只在需要精确控制时使用watch

总结:

computed

  • 自动追踪依赖关系
  • 懒计算(在访问时执行)
  • 结果缓存(依赖未变则返回缓存)
  • 适用于模板绑定、值派生、多依赖计算

watch

  • 显示声明监听目标
  • 即时响应数据变化
  • 支持异步操作
  • 适用于数据联动、异步操作、复杂副作用处理

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax