【问题标题】:Send index from child component to the parent one to remove array item in v-for - VUE.JS 2将索引从子组件发送到父组件以删除 v-for - VUE.JS 2 中的数组项
【发布时间】:2019-03-04 22:39:56
【问题描述】:

我是一个使用 Vue JS 的小新手,所以我从 Vue 2 开始。

我需要删除一个数组项,但触发该方法的按钮位于模板内,而 v-for 位于父模板内。

这是我的 HTML:

主要

<div id="main">
    <div class="panel-group" id="panelGrp">
        <div class="row panelTopSpacing" v-for="panel in panels" is="panel-row" :panel.sync="panel" :general-fields="generalFields" :assistants="assistants" :companies="companies" :positions="positions"></div>
    </div>
</div>

儿童

//CHILD TEMPLATE 
<template id="panelsTpl">           
        <div class="panel panel-success">
            <div class="panel-heading">                    
                {{panel.title}}
                <a :class="panel.classObj.link" role="button" data-toggle="collapse" data-parent="#panelGrp" :href.sync="'#'+panel.id"></a>
                <i :class="panel.infoIcon"></i>
            </div>
            <div :id.sync="panel.id" :class="panel.classObj.panel">
                <div class="panel-body">
                    <div class="container-fluid" v-if="panel.id === 'genInfo'">                            
                        <div class="row">
                            <div v-for="genField in generalFields" is="general-field" :gen-field.sync="genField"></div>
                        </div>
                    </div>
                    <div class="container-fluid" v-else-if="panel.id === 'assistants'">                            
                        <div class="row">
                            <table class="table table-striped table-responsive table-hover">
                                <tr>
                                    <th>Internal?</th>
                                    <th>Can read?</th>
                                    <th>Position</th>
                                    <th>Name</th>
                                    <th>Company</th>
                                    <th width="50px">&nbsp;</th>
                                </tr>
                                <tr>
                                    <td><input type="checkbox"></td>
                                    <td><input type="checkbox" ></td>
                                    <td></td>
                                    <td><input type="text" class="form-control"></td>
                                    <td></td>
                                    <td><a href="#" @click="addAssistant()"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></a></td>
                                </tr>
                                <tr v-for="(assistnt,index) in assistants" is="assistant-row" :assistant.sync="assistnt"></tr>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </template>

孩子的孩子模板

<template id="asstntsTpl">
        <tr v-if="! editing"> 
            <td>{{ assistant.internal }}</td>
            <td>{{ assistant.allowRead }}</td>
            <td>{{ assistant.positionId | position }}</td>
            <td>{{ assistant.name }}</td>
            <td>{{ assistant.cmpnyId | company }}</td>                    
            <td>
                <a href="#" @click="edit()"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
                <a href="#" @click="remove(index)"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></a>
            </td>
        </tr>
        <tr v-else>
            <td><input type="checkbox" v-model="assistant.internal"></td>
            <td><input type="checkbox" v-model="assistant.allowRead"></td>
            <td><!--<select-position :position="positions" :id.sync="assistant.positionId"></select-position>--></td>
            <td><input type="text" v-model="assistant.name" class="form-control"></td>
            <td><!--<select-company :company="companies" :id.sync="assistant.cmpnyId"></select-company>--></td>                    
            <td><a href="#" @click="update()"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></a></td>
        </tr> 
    </template>

JS:

var main = new Vue({
el: "#main",
data: {
    valid: false,
    new_assistant: {
        id: "",
        name: "",
        internal: true,
        cmpnyId: "",
        positionId: "",
        allowRead: false
    },
    panels: [
        {id: "genInfo", title: "General Info", classObj: {panel: "panel-collapse collapse in", link: ""}, infoIcon: "fas fa-file-alt infoIcon pull-right"},
        {id: "assistants", title: "Assistants", classObj: {panel: "panel-collapse collapse", link: "collapsed"}, infoIcon: "fas fa-users infoIcon pull-right"},
        {id: "agrmtns", title: "Agreements", classObj: {panel: "panel-collapse collapse", link: "collapsed"}, infoIcon: "fas fa-file-signature infoIcon pull-right"}
    ]
    assistants: [
        {id: "1",
            name: "Bob",
            internal: true,
            cmpnyId: "1",
            positionId: "1",
            allowRead: false},
        {id: "2",
            name: "John",
            internal: true,
            cmpnyId: "1",
            positionId: "1",
            allowRead: false}
    ],
    companies: [
        {id: "1", name: "cmpny1"},
        {id: "2", name: "cmpny2"},
        {id: "3", name: "cmpny3"}
    ],
    positions: [
        {id: "1", name: "Pos1"},
        {id: "2", name: "Pos2"},
        {id: "3", name: "Pos3"}
    ]
},
methods: {
    addAssistant: function () {
        this.assistants.push(this.new_assistant);

        this.new_assistant = {
            id: "",
            name: "",
            internal: true,
            cmpny_id: "",
            position_id: "",
            allowRead: false};
    }
}

此时一切正常,但是当我尝试从填充有助手数组的表中删除一行时,它会删除第一行,但是我单击了第二行的垃圾桶图标。

VUE 组件

Vue.component("assistant-row", {
template: "#asstntsTpl",
props: ["nw-assistant", "assistant"],
data: function () {
    return {
        editing: false
    };
},
methods: {
    remove: function (index) {
        this.$parent.assistants.splice(**index**, 1);
    },
    edit: function () {
        this.editing = true;
    },
    update: function () {
        this.editing = false;
    }
}
});

好像 splice 根本不起作用。

PD::: 我知道如何在一个简单的场景中使用它,例如:

<li v-for="cat,index in categories">
    <button @click="remove(index)">Remove</button>
</li>

我做了这个小 jsfiddle 来模拟上面的代码:

https://jsfiddle.net/empiricalDev/eywraw8t/399050/

提前致谢。

问候!

【问题讨论】:

  • Emit an event from the child 告诉父项需要删除,让父项删除。
  • 你能不能访问这个问题stackoverflow.com/questions/52551840/…我觉得和你一样
  • @ElAlamiAnas 我接受了你的建议,我使用了 ``$emit` 函数,请检查答案
  • @empiricalDev 我的回答出了什么问题?
  • 您没有更改 jsfiddle 中的任何内容

标签: javascript vue.js vuejs2 vue-component array-splice


【解决方案1】:

您可以尝试使用this.$emit() 向父组件发出事件,例如this.$emit("delete",this.todo);,其中event 作为第一个参数,this.todo 作为第二个参数,在父组件中添加@delete="removechild" 作为关注:

&lt;tod v-for="(todo, index) in todos" :todo="todo" @delete="removechild"&gt;&lt;/tod&gt;

并在父组件中实现您的removechild,如下所示:

removechild(todo){
  this.todos.splice(this.todos.indexOf(todo),1);
}

注意:

如果您的 prop 是类似 {id:1,name:"todo 1"} 的对象,您可以过滤您的 todos 数组,例如 this.todos= this.todos.filter((item)=&gt;{return item.id!=todo.id});

Vue.component("tod",{
  template:"#tpl",
  props:["todo"],
  methods: {
      remove: function() {
  
        this.$emit("delete",this.todo);
      }
    }
});  

new Vue({
    el: '#app',
    data: {
      todos: ['Buy milk', 'Do exercises', 'Write a book', 'Plant a tree']
    },
    methods:{
    
    removechild(todo){
    this.todos= this.todos.filter((item)=>{return item!=todo});
 
    }
    }
    
  })
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

del {
  color: rgba(0, 0, 0, 0.3);
}
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Vue.delete">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.min.js"></script>
</head>
<body>
  <div id="app">
    <ol>
      <tod v-for="(todo, index) in todos" :todo="todo" @delete="removechild"></tod>
    </ol>
  </div>
  <template id="tpl">
    <li>
        {{todo}}
        <button @click="remove">&times;</button>
    </li>
      
  </template>
</body>
</html>

【讨论】:

  • 谢谢,代替filter试试splice,你可以用indexOf()获取元素索引,你可以查看我的例子codesandbox.io/s/qzrp4p3qw9
  • 您好 Boussadjra,谢谢您的回复。我想我错过了在 jsfiddle 中配置它。我的意思是,v for 也在组件内,而不是在主组件内。 -- vfor panel in panel (inside main) //Parent ---vfor content,index in panel (inside panel tmplte) //Child ----
  • 嗨@boussadjra brahim,我更新了原始帖子中的代码。在那里你可以看到我目前的结构。提前致谢!
猜你喜欢
  • 2021-01-11
  • 2020-11-20
  • 1970-01-01
  • 2019-04-11
  • 2018-07-07
  • 1970-01-01
  • 2017-09-13
  • 2020-09-28
  • 2017-06-10
相关资源
最近更新 更多