computed是只读的派生值,必须基于ref/reactive等响应式数据,不可赋值、不可含异步逻辑;强行赋值会报错,应修改源头数据;setup中仅支持函数式写法,不支持Options API风格的get/set对象语法。

computed 必须基于响应式数据、不能赋值、不能含异步逻辑,否则会报错或失效。
computed 为什么不能直接赋值
它不是普通变量,而是只读的派生值。比如你写了 const fullName = computed(() => firstName.value + ' ' + lastName.value),后续写 fullName.value = 'Li Lei' 会立刻抛出 "Cannot assign to read only property" 错误。
真正该改的是源头:firstName.value = 'Li' 或 lastName.value = 'Lei',fullName 才会自动更新。
- 在
setup语法糖中,必须用computed(() => {})函数调用形式,不能写成 Options API 风格的对象(如{ get() {}, set() {} }) - 即使你显式写了
set,uni-app(基于 Vue 3)默认也不支持双向绑定到computed,强行加set多数场景无意义,还容易掩盖设计问题 - 想实现“输入框双向绑定到计算结果”?那是业务逻辑错位——应把输入绑定到原始字段,让
computed只负责展示加工
过滤列表时怎么避免 Cannot read property 'toLowerCase' of null
用户输入为空、后端返回字段缺失、数组项为 null 都会导致链式调用崩掉。别写 item.name.toLowerCase().includes(keyword)。
- 用可选链:
item.name?.toLowerCase()?.includes(keyword) - ID 搜索记得转字符串:
item.id?.toString().includes(keyword),否则123.includes('2')直接报错 - 别用
new RegExp(keyword, 'i')—— 用户输[abc]就触发SyntaxError: Invalid regular expression;真要正则高亮,先keyword.replace(/[.*+?^${}()|[]\]/g, '\$&')转义
为什么 computed 里不能发请求或做 DOM 操作
它的定位是「同步推导一个值」,不是「执行一件事」。写 await fetch() 会让 computed 返回 Promise,模板里显示 [object Promise];在里头改 document.body.style.color,不仅破坏响应式链路,还会导致缓存失效、竞态问题。
- 需要搜索后拉数据?用
watch(searchText, () => { /* fetch */ }, { immediate: true }) - 需要关键词高亮?别在
computed里拼带v-html的 HTML 字符串,留到模板用v-html或单独封装高亮组件 - 缓存只对同步返回值生效:一旦加了
setTimeout、Promise.then或任何异步分支,computed 就退化成普通函数,失去缓存和响应式优势
最常被忽略的一点:computed 的依赖必须是明确的响应式源(ref、reactive、props),如果依赖了非响应式对象的属性,或者用了 JSON.parse / Object.assign 等切断响应式的操作,它就再也不会更新了。


















