如何在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
相关产品推荐
相关产品推荐

