动态创建组件始终删除最后一个实例

时间:2017-08-13 08:07:44

标签: vue.js vuejs2 vue-component

我有一个child组件和parent组件。父组件动态地(即按需)呈现子组件并将记录保持在数组中。当子组件需要被删除时,它会发出事件,因此传递其id以在记录中进行标识。虽然记录确实基于id被删除但是最后创建的实例被删除了。即使你点击第一个孩子,它也只会删除最后一个孩子。

Here是与我的情况相同的链接,但只是简单的形式。 我对SO进行了研究,发现这个answer的小提琴是here。所以我确实在另一个fiddle中遵循了它的模式,但结果没有什么不同。

我不知道这里的问题是什么......我做错了什么?

更新1:添加了代码

更新2:如果您想跳过

,请检查第一个链接

ChatPanel.vue

 <template>
  <div class="chat-container">
    <div class="columns" style="justify-content: flex-end;">
      <div class="column is-3" style="order: 1;">
        <div class="chat-panel">
          <nav class="panel state" :class="[statusIn ? 'in' : 'out']">
            <p class="panel-heading">
              Arbab Nazar
              <span id="click-handle" @click="toggleState"></span>
            </p>
            <div class="panel-block">
              <p class="control has-icons-left">
                <input class="input is-small" type="text" placeholder="search">
                <span class="icon is-small is-left">
                  <i class="fa fa-search"></i>
                </span>
              </p>
            </div>
            <p class="panel-tabs">
              <a class="is-active">all</a>
              <a>Online</a>
              <a>Sleeping</a>
            </p>

            <chat-list/>
          </nav>
        </div>
      </div>

       <chat-window v-for="(window, index) in windows" 
                    :identity="index" 
                    v-on:remove-window="removeWindow(window)"
      /> 

    </div>
  </div>
</template>

<script>
import ChatList from './ChatList'
import ChatWindow from './ChatWindow'

import Bus from '../Events/Bus.js'

export default {
  name: 'chatpanel',
  data () {
    return {
      statusIn: true,
      windows: [],
      id: Number
    }
  },
  mounted() {
    Bus.$on('new-window', (data)=> {
      this.windows.push((this.windows.length+1))
    })
  },
  methods: {
    toggleState(event) {
      event.stopPropagation()
      this.statusIn = !this.statusIn

    },
    removeWindow(window) {
      this.windows.splice(this.windows.indexOf(window),1)
    }
  },
  components: {
    ChatList,
    ChatWindow
  }
}
</script>

ChatWindow.vue

<template>
    <div class="column is-2">
        <div class="chat-window-container" :class="{'reset': statusIn}">
            <div class="card state" :class="[statusIn ? 'in' : 'out']">
                <header class="card-header">
                    Ahmad Jan
                    <a class="delete" @click="$emit('remove-window')"></a>
                    <span id="click-handle" @click="toggleState"></span>
                </header>
                <div class="card-content">
                    <template v-for="message in messages">
                        <p>
                            {{ message }}
                        </p>
                    </template>
                </div>
            </div>
            <div class="field has-addons">
                <div class="control is-expanded">
                    <input class="input" type="text" 
                            placeholder="Write something amazing..."
                            @keyup.enter="sendMessage" v-model="messageText"
                    >
                </div>
                <div class="control">
                    <a class="button is-primary" 
                        @click="sendMessage"
                        style="background:rgb(0, 184, 255)"
                    >
                    Send
                    </a>
                </div>
            </div>

        </div>
    </div>
</template>
<script>
import Bus from '../Events/Bus.js'

export default {
    props:['identity'],
    data() {
        return {
            messageText: '',
            messages: [],
            statusIn: true,
            id: ''
        }
    },
    created() {
        this.id = this.identity
    },
    methods: {
        sendMessage(event) {
            this.messages.push(this.messageText)
            this.messageText = ''
            console.log('msg', event.target.value)
            // this.messages
        },
        toggleState(event) {
            event.stopPropagation()
            this.statusIn = !this.statusIn

        },
        removeWindow(id) {
            console.log(`remove window with id ${id}`)
            Bus.$emit('remove-window', {id})
        }
    }
}
</script>

ChatList.vue

<template>
    <div style="overflow-y: scroll;max-height: 17.5rem;">
        <template v-for="chat in chats">
            <chatter :user="chat"></chatter>
        </template>
    </div>
</template>
<script>
import Chatter from './Chatter'

export default {
    props:{},
    data () {
        return {
            chats: [
                { name: 'Abdul Hameed', active: true  },
                { name: 'Ahmad Jan', active: false }, 
                { name: 'Murad Surkhab', active: false }, 
                { name: 'Angelo Mathews', active: false }, 
                { name: 'Hasan Ali', active: true }, 
                { name: 'Fakhar-ud-Din', active: true }, 
                { name: 'Sultan Usman', active: true }, 
                { name: 'Muad Saeed', active: false }, 
                { name: 'Saleem Yousaf', active: false }]
        }
    },
    components: {
        Chatter
    }
}
</script>

Chatter.vue

<template>
    <div>
        <a class="panel-block" :class="{'is-active':user.active }" @click="letsCaht">
            <div style="display: flex;">
                <p class="image is-24x24 chat-image" >
                    <img src="http://bulma.io/images/placeholders/96x96.png">
                </p>
                <p class="content">
                    {{user.name}}
                </p>
            </div>
            <span class="panel-icon">
                <i class="fa fa-comments"></i>
            </span>
        </a>
    </div>
</template>
<script>
import Bus from '../Events/Bus.js'

export default {
    props:['user'],
    methods: {
        letsCaht(event) {
            Bus.$emit('new-window', {user: this.user})
            console.log(`${this.user.name} is listening`)
        }
    },
    components: {}
}
</script>

2 个答案:

答案 0 :(得分:3)

我认为你的删除是在第一个小提琴中工作,但是你没有正确看到它,因为如果你删除一个项目,你的列表会变短。所以似乎总是删除最后一项。

同时向对象添加id有助于Vue呈现v-for,您可以将键绑定添加到id。

请查看下面的演示或此fiddle

在您在问题中发布的应用代码中

你的删除处理程序是否被调用?你在公共汽车上排放,但你的听众是附属于此。请查看此fiddle,以便了解其中的差异。

Vue.component('child', {
		props:['index', 'data'],
    template: `
        <div>
            data# {{data}}
            <button @click="$emit('delete-me')">Delete</button>
        </div>`
})

Vue.component('parent', {
    template: `
        <div>
            Keep Adding new Instances 
            <button @click="newChild">New</button>
            <hr />
            <child v-for="(row, index) in children" :data="row" 
            v-on:delete-me="deleteThisRow(index)" :key="row.id"
            :index="index"
            ></child>
        </div>`,
        data() {
        	return {
            id: 0,
          	children:[]
          }
    },
    methods: {
    	newChild() {
      	this.children.push({
        	id: this.id++,
        	value: 'new child'
        })
      },
      deleteThisRow(index) {
      			// console.log('index', index, this.children)
            this.children.splice(index, 1);
        }
    }
})

new Vue({
    el: '#app',
    template: `
        <div>
        		<parent />
            
        </div>
    `,
    
    methods: {
        
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<div id="app"></div>

答案 1 :(得分:0)

每次添加新组件时,都应为新组件添加唯一的 id。

这对我有用。

================================================ ========================

myradio.vue


<template>
    <div>
         <div>
             <label>{{inputVal}}</label>
         </div>
    </div>
</template>

<script>
export default {
  name: 'myradio',
  data () {
    return{
      inputVal:new Date().getTime()//Get timestamp
    }
  }

}
</script>


mysurvey.vue


<template>
    <div>

        <div>
            <button v-on:click="addNewRadio">addNewRadio</button>
        </div>
        <hr>
         <div v-for="(item,index) in radioComponents" :key="item.myid">
             <li v-bind:is="item.myComponent"></li>
             <button v-on:click="delRadio(index)">delRadio</button>
             <hr>
         </div>
    </div>
</template>

<script>

import myradio from '@/myComponent/myradio'

export default {
  name: 'mysurvey',
  components: {
    myradio
  },
  data () {
    return {
      radioComponents: [
        {
          myid:1,
          myComponent:myradio
        },
        {
          myid:2,
          myComponent:myradio
        }
      ]
    }
  },
  methods: {
    addNewRadio:function(){
      let size=this.radioComponents.length+1;
      var json={
        myid:size,
        myComponent:myradio
      };
      this.radioComponents.push(json);
    },
    delRadio:function (index) {
      this.radioComponents.splice(index, 1);
    }
  }

}
</script>