← 返回文章列表
Vue·1010 次阅读

Vue 2 计算属性与侦听器:什么时候用哪个

Vue 2 计算属性与侦听器:什么时候用哪个

刚上手 Vue 时最容易纠结的问题之一:数据变了要做点事,到底写 computed 还是 watch?官方文档说得很简洁,但实际写起来还是会混。整理一下自己的理解。

一句话分工

  • computed:从已有数据派生出一个新值,模板里直接用
  • watch:数据变化时执行一段副作用(发请求、操作 DOM、写 localStorage……)

判断标准很简单:你需要的是一个"值"还是一次"动作"?

computed:派生值,自带缓存

new Vue({
  data() {
    return {
      firstName: 'Dong',
      lastName: 'Xu',
    }
  },
  computed: {
    fullName() {
      console.log('重新计算了')
      return this.firstName + ' ' + this.lastName
    },
  },
})

模板里多次引用 fullName,只要依赖没变,计算函数只跑一次——这是 computed 和 methods 的本质区别。methods 每次渲染都会重新执行,computed 按依赖缓存。

用 methods 实现同样的效果,功能上没问题,但列表渲染几百个节点、每个节点调三四个方法时,性能差距就出来了。

computed 的 setter

计算属性默认只读,但也可以写 setter,做双向派生很方便:

computed: {
  fullName: {
    get() {
      return this.firstName + ' ' + this.lastName
    },
    set(val) {
      const parts = val.split(' ')
      this.firstName = parts[0]
      this.lastName = parts[1] || ''
    },
  },
}

v-model="fullName" 就能直接用了。

watch:变化时执行副作用

watch: {
  keyword(newVal, oldVal) {
    this.page = 1
    this.fetchList() // 搜索词变化,重置页码并重新请求
  },
}

两个实用选项:

  • immediate: true:初始化时立即执行一次,省掉 created 里手动调一遍
  • deep: true:深度监听对象内部变化。注意 deep 监听大对象有性能成本,能监听具体路径就写 'form.name' 这种点路径
watch: {
  keyword: {
    handler(val) {
      this.fetchList()
    },
    immediate: true,
  },
}

常见误用

1. 用 watch 做派生值

// 反例:watch 同步另一个 data
data() {
  return { firstName: '', lastName: '', fullName: '' }
},
watch: {
  firstName(val) { this.fullName = val + ' ' + this.lastName },
  lastName(val) { this.fullName = this.firstName + ' ' + val },
}

两行 computed 能解决的事,写了两个 watch 还多出一个冗余 data,依赖一多直接失控。这是典型的该用 computed 的场景。

2. 在 computed 里发请求

computed 应该是纯函数,同样的依赖永远返回同样的结果。在里面发请求,一来返回值拿不到异步结果,二来每次重新计算都会触发请求,完全不可控。

3. watch 里改自己监听的值

容易写出无限循环。真要改,记得加条件判断出口。

速查表

场景 选择
模板里展示由其他数据算出来的值 computed
数据变了要发请求 / 存缓存 / 手动操作 DOM watch
需要拿到旧值做对比 watch
初始化就要执行一次 watch + immediate
派生值还要支持 v-model computed setter

一句话:能用 computed 的地方优先 computed,它是声明式的、可缓存的;watch 留给那些"真的要做点什么"的时刻。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4