computed 同时写 get() 和 set()

在 Vue 实际项目里,computed 同时写 get()set()核心场景就是:把一个值 "加工后使用",同时又能 "修改后自动同步回源头"

最典型、最实用的场景:

  1. 表单绑定一个计算后的变量(比如全选 / 反选、格式化输入)
  2. 对 props 进行双向绑定(Vue 不建议直接改 props,用 computed 中转)
  3. 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既要计算展示,又要能修改并同步回源头

适合:双向绑定 + 状态中转 + 表单格式化 + 全选反选

相关推荐
Highcharts.js3 小时前
Highcharts + TypeScript 集成高级技巧|类型与框架集成实战
前端·javascript·vue.js·react.js·typescript·highcharts·图表生成
芒果8013 小时前
做文档配图太烦?一个小时写了个工具解决
前端
luanma1509803 小时前
Vue2 vs Vue3:核心区别全解析
前端·javascript·vue.js
qq_381338503 小时前
Vue 3 组合式 API 最佳实践:从入门到精通
前端·javascript·vue.js
石头猫灯3 小时前
DNS + Web 服务集成实验
前端
小王码农记3 小时前
el-input限制只能输入价格格式
前端·vue.js
云霄IT3 小时前
安卓apk逆向之crc32检测打补丁包crc32_patcher.py
java·前端·python
小句3 小时前
Java Web 技术演进:Servlet → Spring → Spring Boot
java·前端·spring
ljt27249606613 小时前
Flutter笔记--popUntilWithResult
前端·笔记·flutter