2017-10-17 68 views
3

我在Vue中實現動態模態組件時遇到問題。帶Vue的多個模態組件

我遵循顯示從數據庫獲取的一組數據的一種常見方法是通過迭代db結果的每一行來轉儲HTML表格元素中的每一行。像這樣:enter image description here

正如你在截圖中看到的,每一行都有一個或多個由循環動態生成的按鈕。 爲了將一個模式組件綁定到每個按鈕(比如這個場景中的Remove按鈕),我做了這樣的事情。
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

正如我開始明白前端,後端的關係,我的學習,這種模式在應用程序中更頻繁地出現。我如何解決這個問題(一個非常適合初學者的水平)?

回答

2

根本問題是,您在所有模態組件上引用相同的數據屬性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>

+0

接收應該顯示適用的數據在一個'模式,button'成分的情況下,單一modal組件脫身,如果我希望數據屬性名稱和'@ trigger'中的函數是用戶提供的,而不是靜態的'showModal'和'onShowModal'道具和函數。我的意思是這樣的:''? – Eisenheim

+1

在這種情況下,'modal-btn'組件中的'@ trigger'處理程序應該發出一個事件(比如''emit('show')'),然後父組件應該通過' thanksd

+0

謝謝,這會照顧事件的發射。但是如何在''中的'v-if'指令?我如何將v-value的值綁定到用戶選擇的數據屬性說'showConfirmModal'?我堅持使用'' – Eisenheim

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 
    } 
    } 
}); 

 

而這裏的updated JSBin

如果你需要不同的情態動詞對於每種按鈕類型,則只需創建兩個按鈕組件edit-button,delete-button

1

您可能需要更多以數據爲中心的應用程序蟑螂對你正在嘗試。喜歡的東西,

<!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> 

然後,您可以還與通過prop