news 2026/8/11 3:36:05

计算属性与侦听器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
计算属性与侦听器

计算属性与侦听器

  • computed:从现有数据“算”出新数据(有缓存,无副作用)
  • watch:监听数据变化,执行副作用(如请求、日志、操作上报)

1. 计算属性 computed

为什么需要computed?

模板中直接写复杂表达式会导致臃肿、重复、不可复用。
把“根据现有数据算出新数据”的逻辑放在<script setup>中,模板只负责渲染。

基本用法

import{ref,computed}from'vue'constkeyword=ref('')constusers=ref([...])// 源数据constfilteredUsers=computed(()=>{returnusers.value.filter(user=>user.name.includes(keyword.value))})

三个要点

  1. 模板中直接使用,不要加.value(自动解包):v-for="user in filteredUsers"
  2. 脚本中必须用.value读取值:filteredUsers.value.length
  3. 只读:不能给计算属性赋值,要改变结果就修改它依赖的源数据

缓存特性

  • computed 会缓存计算结果,只有当依赖的响应式数据变化时才重新计算
  • 多次使用同一个计算属性,只会执行一次计算(后续读缓存)

对比普通方法

  • 方法每次被调用都会重新执行(无论依赖是否变化)
  • 模板渲染时多次调用方法就会执行多次,无缓存

类比:computed 像电子价目牌(商品不变就不动),方法像收银员每接一个任务就重新计算

误区:计算函数里如果使用了非响应式数据(如Date.now()),Vue 无法感知变化,缓存不会失效。

典型应用:搜索 + 筛选

同时根据关键字和状态过滤列表,两个条件用 AND 叠加:

constkeyword=ref('')conststatusFilter=ref('全部')constfilteredUsers=computed(()=>{returnusers.value.filter(user=>{constmatchKeyword=keyword.value===''||user.name.includes(keyword.value)||user.dept.includes(keyword.value)constmatchStatus=statusFilter.value==='全部'||user.status===statusFilter.valuereturnmatchKeyword&&matchStatus})})

模板中直接遍历filteredUsers,人数统计直接用filteredUsers.length


2. 侦听器 watch

与 computed 的区别

  • computed 是纯计算,不应包含副作用(请求、日志等)
  • watch 专门用于数据变化时执行副作用

口诀:能算就用 computed,要动才用 watch

基本用法

import{ref,watch}from'vue'constkeyword=ref('')watch(keyword,(newVal,oldVal)=>{console.log(`关键词从「${oldVal}」变为「${newVal}`)// 可以在这里:发请求、记日志、保存数据等})

回调参数:(新值, 旧值)

监听多个数据源

watch([keyword,statusFilter],([newKeyword,newStatus],[oldKeyword,oldStatus])=>{// 任一数据变化都触发})

防抖处理(debounce)

连续触发时,只执行最后一次(如输入暂停 500ms 后再发起请求):

lettimer=nullwatch(keyword,(newVal)=>{clearTimeout(timer)timer=setTimeout(()=>{// 执行上报或请求},500)})

清除上一次的定时器,保证只有停止输入超过指定时间才会执行。

选项:immediate(立即执行)

  • 默认 watch 只在数据第一次变化后才触发
  • 设置immediate: true可在页面初始化时立即执行一次回调(此时oldValueundefined
watch(statusFilter,(newVal)=>{// 初始化时也会执行},{immediate:true})

常用于:进入页面立即加载数据、记录初始状态等。

选项:deep(深度监听)

  • 普通 watch 只监听引用类型变量的引用变化(如数组整体替换)
  • 如果需要监听对象内部属性或数组元素变化,设置deep: true
watch(users,()=>{// 当 users 数组内某个对象的属性被修改时触发},{deep:true})

注意事项

  • deep有性能损耗,大对象或深层嵌套对象要小心使用
  • 深度监听时回调中的新旧值是同一个引用,无法获得变化前的快照(newVal === oldVal
  • 如果需要获取旧值,自己在外层保存快照

监听 reactive 对象的某个属性(getter 形式)

import{reactive,watch}from'vue'conststate=reactive({name:'张三',age:30})watch(()=>state.name,(newVal,oldVal)=>{// 只监听 name 属性,无需 deep})

这种写法更精确、性能更好。


3. computed vs watch 选型总结

computedwatch
用途派生数据(计算新值)执行副作用(动作)
返回值有返回值,可直接在模板使用无返回值,只执行回调
缓存有(依赖不变不重复计算)无(每次变化都触发)
触发条件依赖变化时自动重新计算被监听数据变化时执行回调
典型场景搜索过滤、列表统计、格式化显示数据变化请求接口、日志上报、防抖搜索、配置保存
依赖多个数据多个响应式数据都可作为依赖可监听单个或多个数据源
异步支持不能包含副作用适合放异步请求

选择原则

  • 需要得到一个新数据→ computed
  • 需要在数据变化时做一件事→ watch

两者常配合使用,并非二选一。


4. 关键代码速查

搜索筛选(computed)

constfilteredUsers=computed(()=>{returnusers.value.filter(user=>{constmatchKeyword=keyword.value===''||user.name.includes(keyword.value)||user.dept.includes(keyword.value)constmatchStatus=statusFilter.value==='全部'||user.status===statusFilter.valuereturnmatchKeyword&&matchStatus})})

联动上报(watch + 防抖)

lettimer=nullwatch([keyword,statusFilter],([newKeyword,newStatus])=>{clearTimeout(timer)timer=setTimeout(()=>{addLog(`筛选条件已变化:关键字「${newKeyword}」、状态「${newStatus}`)},500)})

immediate + deep 示例

// 页面打开立即记录当前筛选状态watch(statusFilter,(newStatus)=>{addLog(`当前筛选状态为「${newStatus}`)},{immediate:true})// 监听用户列表内部变化watch(users,()=>{addLog('用户列表数据发生变化')},{deep:true})

5. 常见错误排查

现象原因解决
模板中filteredUsers.value报错模板自动解包,不需要.value直接写filteredUsers
搜索无效,列表不变v-for仍遍历源数据users改为filteredUsers
给计算属性赋值报错computed 只读修改依赖的源数据
点击“切换状态”日志不触发没有加deep: true监听对象/数组内部变化需加deep
每输入一个字符都上报缺少防抖clearTimeout/setTimeout控制
刷新页面没有初始化日志忘记immediate: true在 watch 配置中添加
deep 监听时新、旧值相同深度监听的新旧值是同引用需要旧值请自行深拷贝保存
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/11 3:35:14

AI Agent核心架构解析与主流框架实战指南

1. 从工具到伙伴&#xff1a;AI Agent的范式革命 如果你最近关注AI领域&#xff0c;会发现一个词的热度正在急剧攀升&#xff0c;甚至盖过了年初大火的“RAG”&#xff08;检索增强生成&#xff09;&#xff0c;那就是“AI Agent”。它不再是实验室里的概念&#xff0c;而是正在…

作者头像 李华
网站建设 2026/8/11 3:34:55

C++课后习题训练记录Day184

1.练习项目 &#xff1a;问题描述给定一棵树&#xff0c;树中包含 n 个结点&#xff0c;编号为 1∼n &#xff0c;以及 n−1 条无向边&#xff0c;每条边都有一个权值。现从树中任选一个点&#xff0c;从该点出发&#xff0c;在不走回头路的情况下找出二条到其他点的路径&#…

作者头像 李华
网站建设 2026/8/11 3:34:09

中兴光猫超级权限解锁终极指南:三步获得工厂模式控制权

中兴光猫超级权限解锁终极指南&#xff1a;三步获得工厂模式控制权 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 你是否遇到过想要调整光猫设置却被权限限制的困扰&#xff1f;zteOn…

作者头像 李华
网站建设 2026/8/11 3:33:59

AI Agent可观测性实战:基于OpenTelemetry构建透明决策链路

1. 项目概述&#xff1a;为什么我们需要“看见”Agent的思考过程&#xff1f;在AI Agent&#xff08;智能体&#xff09;技术日益成为应用开发核心的今天&#xff0c;我们正面临一个普遍的困境&#xff1a;Agent的决策过程就像一个“黑盒”。你输入一个复杂的任务&#xff0c;比…

作者头像 李华
网站建设 2026/8/11 3:30:10

Kafka在大数据架构中的核心应用与优化实践

1. Kafka在大数据架构中的核心定位Kafka作为分布式消息队列系统的代表&#xff0c;已经成为现代大数据架构中不可或缺的基础组件。它最初由LinkedIn开发&#xff0c;后来成为Apache顶级项目&#xff0c;其高吞吐、低延迟的特性完美契合了大数据场景下海量数据流转的需求。在实际…

作者头像 李华
网站建设 2026/8/11 3:28:56

Windows蜜罐部署实战:从零构建主动防御与威胁感知系统

1. 为什么要在Windows上部署蜜罐&#xff1f;一个被忽视的防御视角在大多数人的印象里&#xff0c;蜜罐&#xff08;Honeypot&#xff09;似乎是安全研究员、大型企业或者云服务商的专属玩具&#xff0c;通常部署在Linux服务器上&#xff0c;用来捕获针对SSH、Web服务的自动化攻…

作者头像 李华