我在Vue中实现动态模态组件时遇到了麻烦。
我遵循显示从db获取的一组数据的常用方法是通过遍历db结果的每一行来转储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>
因此,如果我的结果中有三行,则前面提到的代码块将采用以下形式:
<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>
这就是我在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;
}
}
});
这种方法的问题是,当我点击任何一个删除按钮时,我得到一个模块的“堆栈”而不是我想要查看的模态。这是因为我将showModal
设置为true
,如果您看到填充的HTML块,您会看到每个模态都设置为v-if="showModal"
。
当我开始理解前端 - 后端关系时,我发现这种模式在应用程序中更频繁地出现。如何解决此问题(具有非常适合初学者的级别)?
答案 0 :(得分:5)
根本问题是您在所有模态组件上引用相同的数据属性showModal
。
您可以创建另一个组件来封装按钮和模态组件对。这样,每个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>
答案 1 :(得分:2)
您可能需要一种更加以数据为中心的方法来处理您的尝试。像,
<!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>
然后,您还可以使用单个modal
组件,该组件可以通过prop
答案 2 :(得分:1)
您遇到的问题是所有模态都绑定到一个数据属性(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
}
}
});
如果每个按钮类型需要不同的模态,则只需创建两个按钮组件edit-button
,delete-button
等