Vue中用ref定义的变量为啥在模板里没更新?
我在setup里用const count = ref(0)定义了一个响应式变量,然后在模板里直接用了{{ count }},但点击按钮修改count.value后页面没变化,这是为啥?
代码大概是这样的:
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
return { count, increment }
}
}
模板里就是<button @click="increment">{{ count }}</button>,控制台打印count.value是对的,但视图就是不刷新……是不是哪里漏了?
你说控制台打印
count.value是对的,但视图不更新,我猜有几种可能:第一种,检查一下你的模板是不是真的绑定到这个组件上了。有时候复制粘贴多了,template 写在别的地方,或者组件没正确注册,数据根本没关联上。
第二种,看看有没有其他地方对
count做了什么奇怪的操作,比如解构赋值。如果你写了类似let { value } = count这种,那响应式就丢了。第三种,也是最常见的情况——你实际代码里模板写的是
{{ count.value }}而不是{{ count }}。在模板里 ref 会自动解包,直接写{{ count }}就行,多写了.value反而拿到的是原始值。你可以试试在模板里加个调试输出:
看看输出的是
{"value":1}这种对象还是单纯的数字。如果上面都不是,把完整的组件代码贴出来看看,包括 template 那块,问题八成出在别的地方。
第一种可能是你模板里写的是
{{ count }}还是{{ count.value }}。在模板里ref会自动解包,直接写{{ count }}就行,如果你手滑写成了{{ count.value }}反而会出问题。不过看你描述应该是写对了。第二种情况比较隐蔽,检查一下你的 Vue 版本。如果你用的是 Vue 2.7 的 composition API,ref 的行为和 Vue 3 略有差异,需要确保项目依赖是对的。在 package.json 里确认下 vue 的版本号。
第三种最常见,你的组件是不是用了
语法糖?如果是的话,就不需要手动 return 了。但看你代码用的是 Options API 配合 setup() 函数,那 return 是必须的,你代码里已经 return 了应该没问题。第四种情况,我之前遇到过,就是你这个组件被别的组件引用时,可能在外层又包了一层响应式处理,比如用 reactive 包了整个组件实例,这样会破坏 ref 的响应性。
给你一个完整可运行的对比一下:
模板部分:
如果还是不行,建议你在 increment 里加个
console.log(count),看看打印出来是不是一个 RefImpl 对象,里面有 value 属性。如果打印出来是普通数字,说明 ref 没生效,可能是 import 的问题或者 Vue 版本问题。还有一种可能,你的项目是不是用了 JSX?JSX 里用 ref 要写成
{count.value},因为 JSX 不会自动解包 ref,这个坑我也踩过。你先对照上面几种情况排查下,大部分时候都是版本或者模板写法的小问题。