【问题标题】:Multiple modal components with Vue使用 Vue 的多个模态组件
【发布时间】:2018-03-29 05:10:42
【问题描述】:

我在 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"

Click here to see a demo

随着我开始了解前端-后端关系,我了解到这种模式在应用程序中出现得越来越频繁。我该如何解决这个问题(非常适合 vue 初学者)?

【问题讨论】:

    标签: javascript php vue.js vue-component


    【解决方案1】:

    根本问题是您在所有模态组件上引用相同的数据属性showModal

    您可以制作另一个组件来封装按钮和模态组件对。这样,每个 modalbtn 对都有一个单独的 showModal 数据属性:

    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>

    【讨论】:

    • 对于modal-button 组件,如果我希望用户提供@trigger 中的数据属性名称和要执行的函数而不是静态showModal 和@987654330,该怎么办? @prop 和函数。我的意思是这样的:&lt;modal-button functoexec="onShowConfirmModal" modaltype="showConfirmModal"&gt;&lt;/modal-button&gt;?
    • 在这种情况下,modal-btn 组件中的@trigger 处理程序应该发出一个事件(比如$emit('show')),然后父组件应该通过&lt;modal-btn @show="onShowConfirmModal&gt; 处理该事件
    • 谢谢,它负责事件发射。但是&lt;modal&gt; 中的v-if 指令呢?如何将 v-if 的值绑定到用户选择的数据属性showConfirmModal?我坚持&lt;modal v-if="iAmAFixedProperty"&gt;
    • 不确定您的意思,为什么不直接使用v-if 中的showModal 属性?
    • 感谢这个解决方案,我也遇到了类似的问题并遇到了这个@thanksd
    【解决方案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 显示的适用数据

    【讨论】:

      【解决方案3】:

      您遇到的问题是所有模式都绑定到一个数据属性 (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
          }
        }
      });
      

       

      这是updated JSBin

      如果您需要为每种按钮类型提供不同的模态,那么只需创建两个按钮组件edit-buttondelete-button

      【讨论】:

        猜你喜欢
        • 2023-04-10
        • 2023-03-26
        • 2019-04-15
        • 2017-10-10
        • 1970-01-01
        • 1970-01-01
        • 2018-01-09
        • 1970-01-01
        • 2020-12-28
        相关资源
        最近更新 更多