Multiple modal components with Vue

早过忘川 提交于 2019-12-04 13:58:28

The root issue is that you are referencing the same data property showModal on all of the modal components.

You could make another component to encapsulate the button and modal component pair. This way there is a separate showModal data property for each modal and btn pair:

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>

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 modal component that receives the applicable data it should display via a prop

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 showModal attribute rather than emitting it to the parent:

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-button etc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!