在 Vue 实际项目里,computed 同时写 get() 和 set(),核心场景就是:把一个值 "加工后使用",同时又能 "修改后自动同步回源头"。
最典型、最实用的场景:
- 表单绑定一个计算后的变量(比如全选 / 反选、格式化输入)
- 对 props 进行双向绑定(Vue 不建议直接改 props,用 computed 中转)
- Vuex / Pinia 状态的双向绑定
1. 最常用:Pinia/Vuex 状态双向绑定
直接用 v-model 绑定 store 里的数据,又不想写一堆 $patch。
<template>
<input v-model="searchText" placeholder="搜索" />
</template>
<script setup>
import { computed } from 'vue'
import { useSearchStore } from '@/stores/search'
const searchStore = useSearchStore()
// 既能读,又能写
const searchText = computed({
// get:从 store 取值
get() {
return searchStore.keyword
},
// set:输入框修改时,自动提交到 store
set(val) {
searchStore.setKeyword(val)
}
})
</script>
作用 :页面里直接 v-model,逻辑层统一交给 store。
2. 对 props 做双向绑定(避免直接修改 props)
Vue 规则:子组件不能直接改 props ,但表单又要 v-model。
父组件
<template>
<Child v-model:username="name" />
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const name = ref('')
</script>
子组件 Child.vue
<template>
<input v-model="localUsername" />
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps(['username'])
const emit = defineEmits(['update:username'])
const localUsername = computed({
get() {
return props.username
},
set(val) {
// 不直接改 props,而是 emit 出去
emit('update:username', val)
}
})
</script>
作用:安全实现双向绑定,符合 Vue 单向数据流规范。
3. 全选 / 反选(业务最常见)
列表多选 + 全选按钮,必须用 get + set。
<template>
<div>
<label><input type="checkbox" v-model="allChecked" /> 全选</label>
<div v-for="item in list" :key="item.id">
<input type="checkbox" v-model="item.checked" /> {{ item.name }}
</div>
</div>
</template>
<script setup>
import { computed, reactive } from 'vue'
const list = reactive([
{ id: 1, name: '苹果', checked: false },
{ id: 2, name: '香蕉', checked: false },
{ id: 3, name: '橘子', checked: false }
])
const allChecked = computed({
// get:判断是否全部选中
get() {
return list.every(item => item.checked)
},
// set:点击全选,批量修改
set(val) {
list.forEach(item => {
item.checked = val
})
}
})
</script>
4. 表单数据格式化(手机号、金额、去空格)
输入时自动处理格式,又能正常绑定。
<template>
<input v-model="phone" placeholder="请输入手机号" />
</template>
<script setup>
import { computed, ref } from 'vue'
const rawPhone = ref('')
const phone = computed({
get() {
// 显示时去掉空格
return rawPhone.value.replace(/\s/g, '')
},
set(val) {
// 输入时只保留数字,自动格式化
const numbers = val.replace(/\D/g, '')
rawPhone.value = numbers
}
})
</script>
一句话总结
- 只有
get:依赖其他值做计算展示 - 有
get + set:既要计算展示,又要能修改并同步回源头
适合:双向绑定 + 状态中转 + 表单格式化 + 全选反选。