Vue跨组件数据与方法调用:非父子组件表格行删除方案
其实你的form-row组件和根组件(thead所在的组件)是父子关系哦,根组件直接使用了form-row,所以我们可以直接利用Vue的父子组件事件传递来实现删除功能,这是最直接的方案。如果真的遇到完全无关联的非父子组件场景,也可以用事件总线来解决,下面分别给你两种方案的实现:
方案一:利用父子组件事件传递(最适配你的场景)
步骤1:修改form-row组件的删除逻辑
首先注意:delete是JavaScript的关键字,不能作为方法名,我们改成handleDelete;然后给组件新增一个index属性接收当前行的索引,点击删除按钮时触发自定义事件把索引传递给父组件:
Vue.component("form-row", { template: "#row-template", props: { itemname: String, quantity: Number, sellingprice: Number, amount: Number, index: Number // 新增:接收当前行的索引 }, methods: { handleDelete() { // 触发自定义事件,把当前行索引传给父组件 this.$emit("delete-row", this.index); } }, // 原有计算属性保持不变 computed: { quantitySynced: { get() { return this.quantity; }, set(v) { this.$emit("update:quantity", +v); } }, sellingpriceSynced: { get() { return this.sellingprice; }, set(v) { this.$emit("update:sellingprice", +v); } }, amountSynced() { this.$emit("update:amount", parseFloat(this.quantity) * parseFloat(this.sellingprice)); return this.amount } } });
同时修改组件模板里的删除按钮,绑定点击事件:
<script type="text/x-template" id="row-template"> <tr> <!-- 原有td内容保持不变 --> <td> <button @click="handleDelete">Delete</button> </td> </tr> </script>
步骤2:在根组件中监听事件并实现删除
在根组件的form-row标签上,传递index属性,并监听delete-row事件,绑定删除方法:
<tbody> <form-row v-for="(row, key) in tableDatas" :key="key" :index="key" v-bind.sync="row" @delete-row="deleteRow" ></form-row> </tbody>
然后在根组件的methods里添加删除逻辑:
new Vue({ el: "#app", data() { return { tableDatas: [] }; }, methods: { btnOnClick(v) { this.tableDatas.push({ itemname: "item", quantity: 1, sellingprice: 55, amount: 55 }); }, deleteRow(index) { console.log("Removing row at index:", index); this.tableDatas.splice(index, 1); } }, computed: { calculate() { return ( this.tableDatas.reduce((total, { amount }) => total + amount, 0) || 0 ); } } });
方案二:事件总线(适用于真正的非父子组件)
如果你的两个组件完全没有父子关联(比如在不同路由页面、嵌套层级极深),可以用Vue事件总线实现跨组件通信:
步骤1:创建全局事件总线
在Vue实例创建前,定义一个全局总线实例:
// 创建全局事件总线 const EventBus = new Vue();
步骤2:在form-row组件中触发删除事件
修改handleDelete方法,通过事件总线向外发送删除信号:
methods: { handleDelete() { // 触发总线事件,传递当前行索引(需要先接收index prop) EventBus.$emit("delete-table-row", this.index); } }
步骤3:在根组件中监听事件并处理
在根组件的created钩子中监听总线事件,实现删除逻辑,同时记得在组件销毁时移除监听避免内存泄漏:
new Vue({ el: "#app", data() { return { tableDatas: [] }; }, created() { // 监听总线的删除事件 EventBus.$on("delete-table-row", (index) => { this.tableDatas.splice(index, 1); }); }, methods: { btnOnClick(v) { this.tableDatas.push({ itemname: "item", quantity: 1, sellingprice: 55, amount: 55 }); } }, computed: { calculate() { return ( this.tableDatas.reduce((total, { amount }) => total + amount, 0) || 0 ); } }, beforeDestroy() { // 组件销毁时移除监听 EventBus.$off("delete-table-row"); } });
小建议
- 优先用方案一,因为你的场景里两个组件本来就是父子关系,原生事件传递更直观,不需要额外的总线实例。
- 尽量不要用数组索引作为
:key(数据有增删时容易出问题),建议给每一行数据加唯一id(比如时间戳),删除时通过id查找索引会更可靠:btnOnClick(v) { this.tableDatas.push({ id: Date.now(), // 临时唯一id itemname: "item", quantity: 1, sellingprice: 55, amount: 55 }); }, deleteRow(id) { const index = this.tableDatas.findIndex(row => row.id === id); if (index !== -1) this.tableDatas.splice(index, 1); }
内容的提问来源于stack exchange,提问作者user11543110
相关产品推荐
相关产品推荐

