动态创建组件总是删除最后一个实例
[英] Creating Component Dynamically always removes last instance
本文介绍了动态创建组件总是删除最后一个实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个 child
组件和 parent
组件.父组件动态呈现子组件,即按需呈现并将记录保存在数组中.当子组件要求删除时,它会发出事件并因此传递其 ID 以在记录中进行标识.虽然记录确实根据 id 被删除,但最后创建的实例总是被删除.即使你点击第一个孩子,它也只会删除最后一个.
这里是与我的情况相同的链接,但只是形式简单.我对 SO 进行了研究,发现这个 answer 的小提琴是 这里.所以我确实在另一个 fiddle 中遵循了它的模式,但结果没有什么不同.
我不知道这里有什么问题...我做错了什么?
更新 1:添加代码
更新 2:如果您想跳过下面的链接,请检查第一个链接
ChatPanel.vue
<模板><div class="chat-container"><div class="columns" style="justify-content: flex-end;"><div class="column is-3" style="order: 1;"><div class="聊天面板"><nav class="面板状态" :class="[statusIn ? 'in' : 'out']"><p class="面板标题">阿尔巴布·纳扎尔<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>
<p class="panel-tabs"><a class="is-active">all</a><a>在线</a><a>睡觉</a></p><聊天列表/></nav>
<chat-window v-for="(window, index) in windows":身份=索引"v-on:remove-window="removeWindow(window)"/>
</模板><脚本>从'./ChatList'导入聊天列表从 './ChatWindow' 导入 ChatWindow从'../Events/Bus.js'导入总线导出默认{name: '聊天面板',数据 () {返回 {状态输入:真,窗户:[],身份证号码}},安装(){Bus.$on('new-window', (data)=> {this.windows.push((this.windows.length+1))})},方法: {切换状态(事件){event.stopPropagation()this.statusIn = !this.statusIn},移除窗口(窗口){this.windows.splice(this.windows.indexOf(window),1)}},成分: {聊天列表,聊天窗口}}
ChatWindow.vue
<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">艾哈迈德·詹<a class="delete" @click="$emit('remove-window')"></a><span id="click-handle" @click="toggleState"></span></标题><div class="card-content"><模板 v-for="消息中的消息"><p>{{ 信息 }}</p></模板>
<div class="field has-addons"><div class="control is-expanded"><输入类=输入"类型=文本"placeholder="写一些很棒的东西..."@keyup.enter="sendMessage" v-model="messageText">
<div class="控件"><a class="button is-primary"@click="sendMessage"风格=背景:rgb(0、184、255)">发送</a>
</模板><脚本>从'../Events/Bus.js'导入总线导出默认{道具:['身份'],数据() {返回 {消息文本: '',消息:[],状态输入:真,ID: ''}},创建(){this.id = this.identity},方法: {发送消息(事件){this.messages.push(this.messageText)this.messageText = ''console.log('msg', event.target.value)//this.messages},切换状态(事件){event.stopPropagation()this.statusIn = !this.statusIn},移除窗口(ID){console.log(`删除带有 id ${id}` 的窗口)Bus.$emit('remove-window', {id})}}}
ChatList.vue
<div style="overflow-y: scroll;max-height: 17.5rem;"><template v-for="chat in chats"><chatter :user="chat"></chatter></模板></模板><脚本>从 './Chatter' 导入 Chatter导出默认{道具:{},数据 () {返回 {聊天记录:[{ 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 }]}},成分: {喋喋不休}}
Chatter.vue
<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="内容">{{用户名}}</p><span class="panel-icon"><i class="fa fa-comments"></i></span></a>
</模板><脚本>从'../Events/Bus.js'导入总线导出默认{道具:['用户'],方法: {letCaht(事件){Bus.$emit('new-window', {user: this.user})console.log(`${this.user.name} 正在监听`)}},成分: {}}
解决方案
我认为您的删除在第一个小提琴中起作用,但您没有正确看到它,因为如果您删除一个项目,您的列表会变得更短.所以似乎总是最后一项被删除.
向你的对象添加一个 id
有助于 Vue 渲染 v-for
并且你可以将键绑定添加到 id.
请看下面的演示或这个 fiddle.
在您在问题中发布的应用程序代码中:
您的移除处理程序被调用了吗?你在公共汽车上发射,但你的听众依附于此.请查看此fiddle,以便您看到不同之处.
Vue.component('child', {道具:['索引','数据'],模板:`<div>数据# {{数据}}<button @click="$emit('delete-me')">删除</button>
`})Vue.component('父', {模板:`<div>不断添加新实例<button @click="newChild">新建</button><小时/><child v-for="(row, index) in children" :data="row"v-on:delete-me="deleteThisRow(index)" :key="row.id":index="索引"></孩子></div>`,数据() {返回 {编号:0,孩子们:[]}},方法: {新孩子(){this.children.push({id:this.id++,值:新孩子"})},删除这行(索引){//console.log('index', index, this.children)this.children.splice(index, 1);}}})新的 Vue({el: '#app',模板:`<div><父母/>
`,方法: {}})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script><div id="app"></div>
I have a child
component and parent
component. Parent component renders child component dynamically i.e. on demand and keeps the record in array. When a child component demands to be removed, it emits event and hence passes down its id to be identified in record. Though the record does get removed based on id but the last created instance is removed, always. Even if you click the first child, it is going to remove the last one only.
Here is the link that is identical to my situation but only in simple form.
I did research on SO and found this answer whose fiddle is here. So I did follow its pattern in another fiddle but result is no different.
I don't know whats the problem here... what I am doing wrong?
Update 1: Added Code
Update 2: Check first link if you want to skip below
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>
解决方案
I think your deleting is working in the first fiddle but you're not seeing it correctly because your list is getting shorter if you're deleting one item. So it seems that always the last item is removed.
Also adding an id
to your object helps Vue to render the v-for
and you can add the key binding to id.
Please have a look at the demo below or this fiddle.
In your application code that you posted in your question:
Is your remove handler called? You're emitting on bus but your listener is attached to this. Please have a look at this fiddle so you're seeing the difference.
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>
这篇关于动态创建组件总是删除最后一个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文