javascript 带有 Vue 的多个模态组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46791340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple modal components with Vue
提问by Tanmay
I am having trouble implementing dynamic modal component in Vue.
我在 Vue 中实现动态模态组件时遇到问题。
A common approach I follow to display a set of data fetched from the db is I dump each of the rows in an HTML table element by iterating over each of the row of the db result. Something like this: 
我用来显示从数据库中获取的一组数据的一种常用方法是通过迭代数据库结果的每一行来转储 HTML 表元素中的每一行。像这样的东西:
As you can see in the screenshot, each of the rows has one or more buttons which are dynamically generated by the loop.
In order to bind a modal component to each of the buttons (say the Remove buttons in this scenario) I do something like this.
HTML:
正如您在屏幕截图中看到的,每一行都有一个或多个由循环动态生成的按钮。为了将模态组件绑定到每个按钮(在这种情况下说是删除按钮),我做了这样的事情。
HTML:
<div id="app">
<?php foreach($result as $x): ?>
<modal v-if="showModal">I am Modal $x</modal>
<btn @trigger="onShowModal">Button $x</btn>
<?php endforeach; ?>
</div>
So if I have three rows in my result, the aforementioned block of code will take the shape of something like this:
因此,如果我的结果中有三行,则上述代码块将采用如下形式:
<div id="app">
<modal v-if="showModal">I am Modal 1</modal>
<btn @trigger="onShowModal">Button 1</btn>
<modal v-if="showModal">I am Modal 2</modal>
<btn @trigger="onShowModal">Button 2</btn>
<modal v-if="showModal">I am Modal 3</modal>
<btn @trigger="onShowModal">Button 3</btn>
</div>
And here is what I do in the JavaScript end:
这是我在 JavaScript 端所做的:
JavaScript:
JavaScript:
Vue.component('btn',{
template: `<button @click="$emit('trigger')"><slot></slot></button>`,
});
Vue.component('modal',{
template: `<p><slot></slot></p>`,
});
new Vue({
el: '#app',
data: {
showModal: false
},
methods: {
onShowModal(){
this.showModal = true;
}
}
});
The problem with this approach is, when I click any one of the Remove buttons, I get a 'stack' of modals instead of the modal I wanted to view. And that's because I am setting showModalto trueand if you see the populated HTML block you will see that each of the modals is set to v-if="showModal".
这种方法的问题是,当我单击任何一个“删除”按钮时,我得到的是一个“堆栈”模态,而不是我想要查看的模态。那是因为我设置showModal为true,如果您看到填充的 HTML 块,您将看到每个模态都设置为v-if="showModal".
And as I am beginning to understand frontend-backend relationship, I am learning that this pattern is appearing more frequently in an application. How do I fix this issue (with a very vue-beginner-friendly level)?
当我开始了解前端-后端关系时,我了解到这种模式在应用程序中出现的频率更高。我如何解决这个问题(具有非常适合 vue 初学者的水平)?
回答by thanksd
The root issue is that you are referencing the same data property showModalon all of the modal components.
根本问题是您showModal在所有模态组件上引用相同的数据属性。
You could make another component to encapsulate the button and modal component pair. This way there is a separate showModaldata property for each modaland btnpair:
您可以制作另一个组件来封装按钮和模态组件对。这样showModal,每个modal和btn对都有一个单独的数据属性:
Vue.component('btn',{
template: `<button @click="$emit('trigger')"><slot></slot></button>`,
});
Vue.component('modal',{
template: `<p><slot></slot></p>`,
});
Vue.component('modal-btn', {
template: `
<div>
<modal v-if="showModal">
<slot>I am a modal</slot>
</modal>
<btn @trigger="showModal = true">Show Modal</btn>
</div>
`,
data() {
return { showModal: false }
}
});
new Vue({
el: '#app',
data: {
showModal: false
},
methods: {
onShowModal(){
this.showModal = true;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<div id="app">
<modal-btn></modal-btn>
<modal-btn>I am another modal</modal-btn>
<modal-btn>I'm a third modal</modal-btn>
</div>
回答by Leon Vismer
You might need a more data centric approach to what you are trying. Something like,
您可能需要一种更加以数据为中心的方法来解决您的尝试。就像是,
<!DOCTYPE html>
<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
</head>
<body>
<div id="app">
<template v-for="item in items">
<modal v-if="item.show">I am a dummy Modal for {{item.name}}</modal>
<btn @trigger="item.show = !item.show">Button for {{item.id}}</btn>
</template>
</div>
<script>
Vue.component('btn',{
template: `<button @click="$emit('trigger')"><slot></slot></button>`,
});
Vue.component('modal',{
template: `<p><slot></slot></p>`,
});
new Vue({
el: '#app',
data: {
items: [
{id: 1, name: 'item 1', show: false},
{id: 2, name: 'item 2', show: false},
{id: 3, name: 'item 3', show: false}
],
showModal: false
},
methods: {
onShowModal(){
this.showModal = true;
}
}
});
</script>
</body>
</html>
You could then also get away with a single modalcomponent that receives the applicable data it should display via a prop
然后,您还可以使用一个modal组件来接收它应该通过prop
回答by craig_h
The issue you are having is that all modals are bound to one data attribute (showModal) so all modals will show when you set this to true. The solution is to isolate each button within it's own component which has it's own showModalattribute rather than emitting it to the parent:
您遇到的问题是所有模态都绑定到一个数据属性 ( showModal),因此当您将其设置为 true 时,所有模态都会显示。解决方案是将每个按钮隔离在它自己的组件中,该组件具有自己的showModal属性,而不是将其发送给父级:
Vue.component('btn',{
template: `<div><button @click="showModal = true"><slot></slot></button>
<modal v-if="showModal">I am a modal for {{button}}</modal></div>`,
props: ['button'],
data(){
return {
showModal: false
}
}
});
And here's the updated JSBin
If you need different modals for each button type, then simply create two button components edit-button, delete-buttonetc
如果你需要不同的情态动词每个按钮类型,然后只需创建两个按钮组件edit-button,delete-button等

