(1)
javascript
const dialogVisible = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
(2)
javascript
const dialogVisible = computed(() => {
return props.modelValue
})
在Vue项目里使用computed,第一种方式和第二种方式有什么区别?这里浅浅的说一下。
这两种 computed 的写法核心区别在于是否支持双向修改。
1. 先看两种写法的核心差异
写法 1:带 getter/setter 的「可写计算属性」
javascript
const dialogVisible = computed({
get: () => props.modelValue, // 读取值时执行
set: (val) => emit('update:modelValue', val) // 修改值时执行
})
这种是带 setter 的计算属性,也叫「可写计算属性」,核心特点:
get函数:负责读取 值(当你访问dialogVisible.value时触发),这里是读取父组件传入的modelValue;set函数:负责修改 值(当你给dialogVisible.value = 新值时触发),这里通过emit把新值传递给父组件,实现「看似修改子组件值,实则同步到父组件」的效果;- 典型场景:Vue 子组件中实现
v-model双向绑定(比如你这里的弹窗显隐控制)。
写法 2:只有 getter 的「只读计算属性」
javascript
const dialogVisible = computed(() => {
// 这里只有「读取逻辑」,本质等价于只写了 get 函数
return props.modelValue
})
这种是只读计算属性(默认只有 getter),核心特点:
- 只有「读取逻辑」,没有「修改逻辑」;
- 如果你尝试给
dialogVisible.value = true,Vue 会直接报错(提示计算属性是只读的); - 典型场景:只需要根据已有数据计算出一个「不需要修改」的值(比如根据列表数据计算总数、根据状态拼接文案)。
2. 举个实际场景的例子,更易理解
假设你做了一个弹窗子组件,父组件用 v-model:visible="showDialog" 控制显隐:
- 用第一种写法(可写):你在子组件里写
dialogVisible.value = false,能通过emit通知父组件把showDialog改成false,实现弹窗关闭(双向同步); - 用第二种写法(只读):你在子组件里写
dialogVisible.value = false,会直接报错,因为这个计算属性只能读、不能改。
3. 语法等价性
其实第二种写法是第一种的「简写形式」,等价于
javascript
const dialogVisible = computed({
get: () => {
return props.modelValue
}
// 没有 set 函数,默认只读
})
总结
- 功能核心 :带
get/set的是「可写计算属性」(支持读写),单函数的是「只读计算属性」(仅支持读); - 使用场景 :需要双向修改(如子组件实现
v-model)用第一种,仅需计算展示值(如统计、拼接)用第二种; - 关键提醒 :只读计算属性强行赋值会报错,可写计算属性的
set里通常需要通过emit/store等方式修改源数据(不能直接改 props)。