You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vuetify动态v-data-table中获取选中产品数据并同步行信息?

解决方案

核心问题分析

你当前的代码存在两个关键问题:v-autocomplete配置冲突(设置了return-object却绑定单个字段name,导致无法获取完整产品对象),以及选中产品后的逻辑未正确实现,没法自动填充价格和计算总价。下面是具体修改步骤:


1. 修正自动完成组件的绑定逻辑

把v-autocomplete的v-model改为绑定当前行的完整产品对象,同时调整事件传递当前行和选中产品:

<template v-slot:[`item.name`]="props">
  <v-autocomplete
    v-model="props.item.producto" <!-- 绑定整个产品对象 -->
    :items="productosDisponibles"
    item-text="name" <!-- 仅指定显示文本字段 -->
    outlined
    dense
    label="Producto"
    return-object
    @change="onProductoSeleccionado(props.item, $event)" <!-- 传递当前行和选中产品 -->
  ></v-autocomplete>
</template>

2. 初始化新增行的结构

修改agregarProductoALaLista方法,给新增行初始化必要字段,避免undefined报错:

agregarProductoALaLista() {
  this.listaProductos.push({
    producto: null, // 存储选中的产品对象
    cantidad: 1,    // 默认数量设为1
    precio: 0,
    total: 0
  });
}

3. 实现选中产品后的填充逻辑

新增onProductoSeleccionado方法,自动填充价格并计算总价:

onProductoSeleccionado(fila, productoSeleccionado) {
  if (productoSeleccionado) {
    fila.precio = productoSeleccionado.precio;
    fila.total = fila.cantidad * fila.precio;
  } else {
    // 取消选中时重置价格和总价
    fila.precio = 0;
    fila.total = 0;
  }
}

4. 监听数量变化,实时更新总价

给数量输入框添加@input事件,实时计算总价:

<template v-slot:[`item.cantidad`]="props">
  <v-text-field
    v-model.number="props.item.cantidad" <!-- 转成数字类型避免字符串计算错误 -->
    label="Cantidad"
    type="number"
    placeholder="Cantidad"
    min="1" <!-- 限制最小数量为1 -->
    @input="actualizarTotal(props.item)" <!-- 数量变化时更新总价 -->
  ></v-text-field>
</template>

对应的方法:

actualizarTotal(fila) {
  if (fila.precio > 0) {
    fila.total = fila.cantidad * fila.precio;
  }
}

5. 调整表头配置(确保字段对应)

确认headers数组的字段与listaProductos结构匹配:

this.headers = [
  { text: 'Nombre', value: 'name' },
  { text: 'Cantidad', value: 'cantidad' },
  { text: 'Precio', value: 'precio' },
  { text: 'Total', value: 'total' },
  { text: 'Acciones', value: 'actions', sortable: false }
];

完整修改后的核心代码片段

<v-data-table
  :headers="headers"
  :items="listaProductos"
  class="elevation-1"
>
  <template v-slot:top>
    <v-toolbar flat>
      <v-toolbar-title>Productos</v-toolbar-title>
      <v-divider class="mx-4" inset vertical></v-divider>
      <v-spacer></v-spacer>
      <v-btn
        color="primary"
        dark
        class="mb-2"
        @click="agregarProductoALaLista"
      >
        Agregar Producto
      </v-btn>
    </v-toolbar>
  </template>
  <template v-slot:[`item.name`]="props">
    <v-autocomplete
      v-model="props.item.producto"
      :items="productosDisponibles"
      item-text="name"
      outlined
      dense
      label="Producto"
      return-object
      @change="onProductoSeleccionado(props.item, $event)"
    ></v-autocomplete>
  </template>
  <template v-slot:[`item.cantidad`]="props">
    <v-text-field
      v-model.number="props.item.cantidad"
      label="Cantidad"
      type="number"
      placeholder="Cantidad"
      min="1"
      @input="actualizarTotal(props.item)"
    ></v-text-field>
  </template>
  <template v-slot:[`item.precio`]="props">
    {{ props.item.precio }}
  </template>
  <template v-slot:[`item.total`]="props">
    {{ props.item.total }}
  </template>
  <template v-slot:[`item.actions`]="{ item }">
    <v-icon small class="mr-2" @click="editItem(item)"> mdi-pencil </v-icon>
    <v-icon small @click="deleteItem(item)"> mdi-delete </v-icon>
  </template>
  <template v-slot:no-data>
    <v-btn color="primary" @click="initialize"> Reset </v-btn>
  </template>
</v-data-table>
data() {
  return {
    headers: [
      { text: 'Nombre', value: 'name' },
      { text: 'Cantidad', value: 'cantidad' },
      { text: 'Precio', value: 'precio' },
      { text: 'Total', value: 'total' },
      { text: 'Acciones', value: 'actions', sortable: false }
    ],
    listaProductos: [],
    productosDisponibles: [
      {
        id: 1,
        name: "Coca-Cola",
        cantidad: 159,
        fat: 6.0,
        precio: 24,
        protein: 4.0,
      },
      {
        id: 2,
        name: "Leche",
        cantidad: 237,
        fat: 9.0,
        precio: 37,
        protein: 4.3,
      },
      {
        id: 3,
        name: "Alfajor",
        cantidad: 262,
        fat: 16.0,
        precio: 23,
        protein: 6.0,
      },
    ]
  }
},
methods: {
  agregarProductoALaLista() {
    this.listaProductos.push({
      producto: null,
      cantidad: 1,
      precio: 0,
      total: 0
    });
  },
  onProductoSeleccionado(fila, producto) {
    if (producto) {
      fila.precio = producto.precio;
      fila.total = fila.cantidad * fila.precio;
    } else {
      fila.precio = 0;
      fila.total = 0;
    }
  },
  actualizarTotal(fila) {
    if (fila.precio > 0) {
      fila.total = fila.cantidad * fila.precio;
    }
  },
  editItem(item) {
    // 自定义编辑逻辑
  },
  deleteItem(item) {
    const index = this.listaProductos.indexOf(item);
    if (index !== -1) {
      this.listaProductos.splice(index, 1);
    }
  },
  initialize() {
    this.listaProductos = [];
  }
}

内容的提问来源于stack exchange,提问作者Agustin Coronel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 07:54:20