🍀实际开发中没想到 computed 在表单中还能这么使用🚀🚀

前言 ✍

业务场景:

后端会返回表单数据,其中表单数据包含列表数据。前端需要对列表数据进行增删查改

前端处理后,最后将最新数据返回给到后端。

假设后端返回的数据结构如下:

js 复制代码
const formData = ref({
  baseAct: {
    name: '活动一',
    shopName: '店铺-四叶草',
    startTime: '2025-08-20 17:44:00'
  },
  productList: [
    { id: 1, productName: '商品一', stock: '12', price: '12.5', disPrice: '11' },
    { id: 2, productName: '商品二', stock: '12', price: '12.5', disPrice: '11' }
  ]
})

回显:编辑修改表单信息。编辑表单信息除了会编辑基础信息外,还会修改商品列表信息,如折扣价,参与活动商品数量等等。

这些问题不大,对其进行表单字段绑定即可。。。。

进入正文 ✍

由于实际情况下 productList 这部分商品数量很多,名称也很相似。

这就导致了用户在查找具体商品进行修改参数时比较麻烦

因此,需要这里增加了一个需求:增加一个搜索框,用于搜索 productList

在这之前,我都是用俩个变量来处理这种情况的:一个用于存放全部 productList ,一个存放搜索结果 searchProductList

js 复制代码
const search = (key) => {
  if (!key.value) {
   searchProductList.value = formData.value.productList.filter(item => item.productName.includes(key.value))
  } else {
    searchProductList.value = formData.value.productList
  }
}
js 复制代码
<el-table :data="searchProductList">
  <el-table-column prop="productName" label="商品名称" />
  <el-table-column prop="stock" label="库存数量">
    <template #default="{ row }">
      <el-input v-model="row.stock"></el-input>
    </template>
  </el-table-column>
  <el-table-column prop="price" label="价格" />
  <el-table-column prop="disPrice" label="折扣价格" />
  <el-table-column prop="operation" label="操作">
    <template #default="{ row }">
      <el-button @click="remove(row)">移除</el-button>
    </template>
  </el-table-column>
</el-table>

此时页面双向绑定 searchProductList 下的 stock 字段,当对其进行修改时,是能够正常响应到 formData

原因是 searchProductListformData.value.productList 产生了地址引用。

目前到这里,没发现什么问题。

问题来了 ✍

实际业务中除了修改原有 productList 中的数据参数值外,还需要对其进行删除和添加

那么此时,我们需要怎么修改,是直接往 searchProductList 还是 productList 添加数据。

给大家三秒钟思考一下。

目前这种情况下,前端需要去维护两个数组 searchProductListproductList

才能确保查询状态没有出现问题

关键来了:

这种情况:需要产生一种效果就是 searchProductList 是 productList 的一个子集 ,只要修改 productList 数据,searchProductList 将能得到体现。

进入主角 computed ✍

computed 则就能产生上面的效果。

js 复制代码
<template>
  <div>
    <el-input v-model="key" style="margin: 12px; width: 200px;" placeholder="请输入关键字"></el-input>
    <el-button @click="add">增加一条数据</el-button>
    <el-table :data="searchProductList">
      <el-table-column prop="productName" label="商品名称" />
      <el-table-column prop="stock" label="库存数量">
        <template #default="{ row }">
          <el-input v-model="row.stock" @change="change"></el-input>
        </template>
      </el-table-column>
      <el-table-column prop="price" label="价格" />
      <el-table-column prop="disPrice" label="折扣价格" />
      <el-table-column prop="operation" label="操作">
        <template #default="{ row }">
          <el-button @click="remove(row)">移除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script setup>
import { computed, ref } from 'vue'

const key = ref('')

const searchProductList = computed(() => {
  if (!key.value) return formData.value.productList
  return formData.value.productList.filter(item => item.productName.includes(key.value))
})

const formData = ref({
  baseAct: {
    name: '活动一',
    shopName: '店铺-四叶草',
    startTime: '2025-08-20 17:44:00'
  },
  productList: [
    { id: 1, productName: '商品一', stock: '12', price: '12.5', disPrice: '11' },
    { id: 2, productName: '商品二', stock: '12', price: '12.5', disPrice: '11' }
  ]
})
</script>

场景验证及代码解释 ✍

🔨 场景一:搜索状态下,数据修改体现到 productList

查询 商品一,然后修改 stock 字段。此时界面绑定的是 searchProductList 而非 productList,通过输出 productList 可以看到,数据修改体现到了表单数据中

🔨 场景二:添加数据,体现到 searchProductList

当前 productList数据如下:

js 复制代码
const formData = ref({
  baseAct: {
    name: '活动一',
    shopName: '店铺-四叶草',
    startTime: '2025-08-20 17:44:00'
  },
  productList: [
    { id: 1, productName: '商品一', stock: '12', price: '12.5', disPrice: '11' },
    { id: 2, productName: '商品二', stock: '12', price: '12.5', disPrice: '11' }
  ]
})

搜索 商品三,是没有搜索到。此时添加一条数据商品三,界面上就显示了该商品

js 复制代码
const add = () => {
  const product = { id: 3, productName: '商品三', stock: '12', price: '12.5', disPrice: '11' }
  formData.value.productList.push(product)
}

关键代码:往 productList 添加,而非往 searchProductList 添加

js 复制代码
formData.value.productList.push(product)

searchProductList 是通过 computed 计算而得:

js 复制代码
const searchProductList = computed(() => {
  if (!key.value) return formData.value.productList
  return formData.value.productList.filter(item => item.productName.includes(key.value))
})

故产生上面所说的效果:

只要修改 productList 数据,searchProductList 将能得到体现。

并且由于是向 productList 添加数据,故此时 formData 也是最新数据。

🔨 场景三:删除数据,体现到 searchProductList

这里的关键也是删除 productList 数据,searchProductList 通过 computed 计算而得。

js 复制代码
const remove = (row) => {
  const productList = formData.value.productList.filter((item) => item.id !== row.id)
  formData.value.productList = productList
  console.log('移除 formData.productList', formData.value.productList)
}

完整代码 ✍

js 复制代码
<template>
  <div>
    <el-input v-model="key" style="margin: 12px; width: 200px;" placeholder="请输入关键字"></el-input>
    <el-button @click="add">增加一条数据</el-button>
    <el-table :data="searchProductList">
      <el-table-column prop="productName" label="商品名称" />
      <el-table-column prop="stock" label="库存数量">
        <template #default="{ row }">
          <el-input v-model="row.stock" @change="change"></el-input>
        </template>
      </el-table-column>
      <el-table-column prop="price" label="价格" />
      <el-table-column prop="disPrice" label="折扣价格" />
      <el-table-column prop="operation" label="操作">
        <template #default="{ row }">
          <el-button @click="remove(row)">移除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script setup>
import { computed, ref } from 'vue'

const key = ref('')

const searchProductList = computed(() => {
  if (!key.value) return formData.value.productList
  return formData.value.productList.filter(item => item.productName.includes(key.value))
})
const formData = ref({
  baseAct: {
    name: '活动一',
    shopName: '店铺-四叶草',
    startTime: '2025-08-20 17:44:00'
  },
  productList: [
    { id: 1, productName: '商品一', stock: '12', price: '12.5', disPrice: '11' },
    { id: 2, productName: '商品二', stock: '12', price: '12.5', disPrice: '11' }
  ]
})

const add = () => {
  const product = { id: 3, productName: '商品三', stock: '12', price: '12.5', disPrice: '11' }
  formData.value.productList.push(product)
}

const remove = (row) => {
  const productList = formData.value.productList.filter((item) => item.id !== row.id)
  formData.value.productList = productList
  console.log('移除 formData.productList', formData.value.productList)
}

const change = () => {
  console.log('修改 searchProductList')
  console.log('表单中的 productList', formData.value.productList)
}
</script>
相关推荐
小小怪下士_---_2 分钟前
uniapp开发微信小程序自定义导航栏
前端·vue.js·微信小程序·小程序·uni-app
前端W3 分钟前
腾讯地图组件使用说明文档
前端
页面魔术6 分钟前
无虚拟dom怎么又流行起来了?
前端·javascript·vue.js
胡gh6 分钟前
如何聊懒加载,只说个懒可不行
前端·react.js·面试
Double__King9 分钟前
巧用 CSS 伪元素,让背景图自适应保持比例
前端
Mapmost11 分钟前
【BIM+GIS】BIM数据格式解析&与数字孪生适配的关键挑战
前端·vue.js·three.js
一涯12 分钟前
写一个Chrome插件
前端·chrome
鹧鸪yy19 分钟前
认识Node.js及其与 Nginx 前端项目区别
前端·nginx·node.js
跟橙姐学代码19 分钟前
学Python必须迈过的一道坎:类和对象到底是什么鬼?
前端·python