2017-06-05 74 views
1

我是vue js的新手,試圖用bootstrap模式來查看更多數據。我的場景是一個包含多個記錄和一個按鈕的表格,可以在引導模式中查看點擊記錄的詳細信息。點擊第一個按鈕後,它會緩存並不會更新它,同時選擇另一個按鈕來查看不同的細節。boostrap modal沒有用vue js v2雙向綁定更新

有沒有人看到我在做什麼錯了?

(這是Laravel,jQuery和VueJS的組合)

HTML表:

<table class="table table-striped"> 
<thead> 
    <tr> 
     <th>E-mail address</th> 
     <th>Status</th> 
     <th>Sent at</th> 
     <th>Expires in</th> 
     <th></th> 
    </tr> 
</thead> 
<tbody> 
    <tr> 
     <td class="v-align-middle"> 
      [email protected] 
     </td> 
     <td class="v-align-middle"> 
      <span class="label label-default"> 
       pending 
      </span> 
     </td> 
     <td class="v-align-middle"> 
      2017-06-05 17:59:15 
     </td> 
     <td class="v-align-middle"> 
      29 days 
     </td> 
     <td> 
      <div class="btn-group pull-right"> 
       <a href="#" class="btn btn-default" data-toggle="modal" data-target="#inviteDetailsModal" data-email="[email protected]"> 
        <i class="fa fa-eye"></i> 
       </a> 
      </div> 
     </td> 
    </tr> 
    <tr> 
     <td class="v-align-middle"> 
      [email protected] 
     </td> 
     <td class="v-align-middle"> 
      <span class="label label-default"> 
       pending 
      </span> 
     </td> 
     <td class="v-align-middle"> 
      2017-06-05 13:27:25 
     </td> 
     <td class="v-align-middle"> 
      29 days 
     </td> 
     <td> 
      <div class="btn-group pull-right"> 
       <a href="#" class="btn btn-default" data-toggle="modal" data-target="#inviteDetailsModal" data-email="[email protected]"> 
        <i class="fa fa-eye"></i> 
       </a> 
      </div> 
     </td> 
    </tr> 
</tbody> 

JavaScript的:

$('[data-target="#inviteDetailsModal"]').on('click', function() { 
    let email = $(this).data('email'), 
     baseUrl = $('html').data('base'); 

    Vue.component('invite-details', { 
     data: function() { 
      return { 
       email: null, 
       token: null, 
       logs: [], 
       expires: null 
      } 
     }, 
     methods: { 
      update: function (data) { 
       this.email = data['email']; 
       this.token = data['token']; 
       this.logs = data['logs']; 
       this.expires = data['expires']; 
      }, 
      fetchData: function() { 
       this.$http.get(baseUrl + '/system/invites/' + email + '/details') 
        .then(response => { 
         this.update(response.body); 
        }, response => { 
         console.log('whoops something went wrong'); 
        }); 
      } 
     }, 
     mounted: function() { 
      this.$el.addEventListener('shown.bs.modal', this.fetchData()); 
     }, 
     beforeDestroy: function() { 
      this.$el.removeEventListener('shown.bs.modal', this.fetchData()); 
     } 
    }); 

    new Vue({ 
     el: '#inviteDetailsModal' 
    }); 
}); 

自舉模式:

<div class="modal fade slide-up" id="inviteDetailsModal" tabindex="-1" role="dialog" aria-hidden="true"> 
<div class="modal-dialog"> 
    <div class="modal-content-wrapper"> 
     <invite-details inline-template> 
      <div class="modal-content" id="details"> 
       <div class="modal-header clearfix text-left"> 
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> 
         <i class="pg-close fs-14"></i> 
        </button> 
        <h5> 
         Invite details for <span class="semi-bold">@{{ email }}</span> 
        </h5> 
        <p class="p-b-10"> 
         <span data-tooltip="true" data-placement="bottom" title="token"> 
          <em>@{{ token }}</em> 
         </span> 
        </p> 
       </div> 
       <div class="modal-body"> 
        <table class="table table-striped"> 
         <thead> 
         <tr> 
          <th>#</th> 
          <th>Sent at</th> 
          <th>Status</th> 
         </tr> 
         </thead> 
         <tbody> 
         <tr v-for="log in logs"> 
          <td>@{{ log.number }}</td> 
          <td>@{{ log.sentAt }}</td> 
          <td>@{{ log.status }}</td> 
         </tr> 
         </tbody> 
        </table> 
       </div> 
       <div class="modal-footer text-center"> 
        <span class="hint-text"> 
         <em>expires in <strong>@{{ expires }}</strong> days</em> 
        </span> 
       </div> 
      </div> 
     </invite-details> 
    </div> 
</div> 

+0

我假設你正在使用一個模式組件,並試圖根據表中特定按鈕更改其內容?在這種情況下,當組件初始安裝時,「掛載」掛鉤只會觸發一次。 – thanksd

+0

這是正確的,那麼我應該如何根據表中點擊的特定按鈕更新模態內容?你有什麼建議嗎? – jaimyborgman

回答

1

好吧,我在深挖得到這個工作,並因爲你提到你是新的VueJS去加倍努力。我承認我的舊的自我在你的代碼,你進入VueJS與jQuery的心態;-)下降的完整代碼之前

首先幾個簡單的音符:

  • 使用表DB行的整數ID引用用戶無處不在。 通過這種方式,當電子郵件更新時,您仍然知道它是誰在 前端。通過檢查代碼中,我看到的是,電子郵件可以改變 (因爲它是一個更新的data屬性,但它也可用於 您GET要求:baseUrl + '/system/invites/' + email + '/details'

  • 隨後,你可以用這個ID很容易地生成唯一實例 你的模態:-)這是你想與VueJS一起工作的方式!

  • 由於您在多個地方使用相同的數據,請查看 Vuex for a store。它可能看起來令人畏懼,但它很好,一旦你掌握了它。在你的情況下,相同的數據集將是 用於原始表模態。如果有人更新, 的一切更新!

  • 使用Vuex,您可以從任何地方觸發更新。現在每次單擊眼睛按鈕時,數據 都會更新。然而,這是 相當哈克,因爲我已經做了模式的模板的按鈕部分, ,每次它被點擊它調用fetchData()(檢查 控制檯)。你想要做的最好的事情就是使用Vuex,並從單一的真值數據集中產生所有的東西。目前,如果 模式的數據更新,原始表格不是。

  • 有了VueJS,創建自己的模態也同樣簡單。 的優勢在於代碼的開銷較小,因爲您可以使用v-if,因此除非實際需要,否則 將不會加載到DOM中。從當前代碼判斷 ,細節按鈕偶爾會被點擊 。

  • 安裝VueJS調試如果您尚未: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd, 它會幫助你「看」引擎蓋下。

好吧,現在的代碼!首先,該行添加到您的app.js文件:

import JaimyTable from './components/stackoverflow/JaimyTable.vue' 

右上面的var app = new Vue({線。並把它添加到您的組件,所以你最終的東西是這樣的:

import JaimyTable from './components/stackoverflow/JaimyTable.vue' 

var app = new Vue({ 

    components: { 
     JaimyTable, 
    }, 

}); 

這裏的JaimyTable.vue文件:

<template> 
    <div class="container"> 
     <table class="table table-striped"> 
      <thead> 
      <tr> 
       <th>E-mail address</th> 
       <th>Status</th> 
       <th>Sent at</th> 
       <th>Expires in</th> 
       <th></th> 
      </tr> 
      </thead> 
      <tbody> 
      <tr> 
       <td class="v-align-middle"> 
        [email protected] 
       </td> 
       <td class="v-align-middle"> 
      <span class="label label-default"> 
       pending 
      </span> 
       </td> 
       <td class="v-align-middle"> 
        2017-06-05 17:59:15 
       </td> 
       <td class="v-align-middle"> 
        29 days 
       </td> 
       <td> 
        <div class="btn-group pull-right"> 

         <jaimy-modal id="1"></jaimy-modal> 

        </div> 
       </td> 
      </tr> 
      <tr> 
       <td class="v-align-middle"> 
        [email protected] 
       </td> 
       <td class="v-align-middle"> 
       <span class="label label-default"> 
        pending 
       </span> 
       </td> 
       <td class="v-align-middle"> 
        2017-06-05 13:27:25 
       </td> 
       <td class="v-align-middle"> 
        29 days 
       </td> 
       <td> 
        <div class="btn-group pull-right"> 

         <jaimy-modal id="2"></jaimy-modal> 

        </div> 
       </td> 
      </tr> 
      </tbody> 
     </table> 
    </div> 
</template> 

<script> 
    import JaimyModal from './JaimyModal.vue' 

    export default { 

     components: { JaimyModal }, 

     props: [], 

     mixins: [], 

     data: function() { 
      return { 
       // 
      } 
     }, 

     computed: { 
      computed_variable() { 
       return ''; 
      } 
     }, 

     created() { 
      // 
     }, 

     mounted() { 
      // 
     }, 

     methods: { 
      // 
     }, 

     watch: { 
      // 
     } 
    } 
</script> 

,並請注意<jaimy-modal id="1"></jaimy-modal>線。您可能想要使用v-for自動生成所有的<tr>行:)確保id=對應於數據庫中的ID。現在

爲所有魔術發生在JaimyModal.vue

<template> 
    <div> 
     <a href="#" class="btn btn-default" data-toggle="modal" :data-target="'#inviteDetailsModal' + id" @click="fetchData()"> 
      <i class="fa fa-eye"></i> 
     </a> 

     <div class="modal fade slide-up" :id="'inviteDetailsModal' + id" tabindex="-1" role="dialog"> 
      <div class="modal-dialog"> 
       <div class="modal-content-wrapper"> 


        <div class="modal-content" id="details"> 
         <div class="modal-header clearfix text-left"> 
          <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> 
           <i class="pg-close fs-14"></i> 
          </button> 
          <h5> 
           Invite details for <span class="semi-bold">{{ email }}</span> 
          </h5> 
          <p class="p-b-10"> 
         <span data-tooltip="true" data-placement="bottom" title="token"> 
          <em>{{ token }}</em> 
         </span> 
          </p> 
         </div> 
         <div class="modal-body"> 
          <table class="table table-striped"> 
           <thead> 
           <tr> 
            <th>#</th> 
            <th>Sent at</th> 
            <th>Status</th> 
           </tr> 
           </thead> 
           <tbody> 
           <tr v-for="log in logs"> 
            <td>{{ log.number }}</td> 
            <td>{{ log.sentAt }}</td> 
            <td>{{ log.status }}</td> 
           </tr> 
           </tbody> 
          </table> 
         </div> 
         <div class="modal-footer text-center"> 
          <span class="hint-text"> 
           <em>expires in <strong>{{ expires }}</strong> days</em> 
          </span> 
         </div> 
        </div> 


       </div> 
      </div> 
     </div> 
    </div> 
</template> 

<script> 
    export default { 

     props: ['id'], 

     data: function() { 
      return { 
       email: null, 
       token: null, 
       logs: [], 
       expires: null, 
       baseUrl: 'https://yourbaseurl.com', 
      } 
     }, 

     mounted: function() { 
      // 
     }, 

     methods: { 
      update: function (data) { 
       this.email = data['email']; 
       this.token = data['token']; 
       this.logs = data['logs']; 
       this.expires = data['expires']; 
      }, 
      fetchData: function() { 
       console.log('data fetched'); 

       // Commented out for local purposes 
//    this.$http.get(this.baseUrl + '/system/invites/' + this.email + '/details') 
//      .then(response => { 
//       this.update(response.body); 
//      }, response => { 
//       console.log('whoops something went wrong'); 
//      }); 

       // Dummy data 
       this.update({ 
        email: '[email protected] ' + this.id + '.com', 
        token: 'token123123asdsasdasdasd', 
        logs: [ 
         { 
          number: 1, 
          sentAt: '2017-01-01', 
          status: 'Ok', 
         }, 
         { 
          number: 2, 
          sentAt: '2017-02-01', 
          status: 'Failed', 
         }, 
        ], 
        expires: '2017-10-01' 
       }); 
      } 
     }, 

    } 
</script> 

重要的是這裏要注意的是在按鍵,其中數字對應道具的ID :data-target="'#inviteDetailsModal' + id"部分。通過使用:,您可以將其作爲表達式,並且可以解析爲唯一的參考。

正如您所看到的設置完全不同於以前。模式是表格行的嵌套組件。一旦你開始將組件視爲外觀和功能的重複部分,但其中包含獨特的數據,事情將快速點擊。把它想象成Laravel的模型。

在被告知需要分離設計(CSS),標記(HTML)和功能(JS)很長一段時間之後,奇怪的是它讓所有人都坐在一個文件中。但擁抱它,你會愛上VueJS:D

給Vuex一看!第二個你得到了多個使用和操作同一個數據集的組件,這是一個上帝派! Ow和最後:第二個你開始考慮使用諸如fn.trigger和whatnot之類的東西,你正在接近VueJS錯誤。牢記這一點:)它具有您使用該頁面所需的所有工具,然後一些!

快樂編碼!

+0

Ahh感謝您提供深入的解釋@stan-smulders,當您的頭腦一直以jQuery等「老」方式訓練時,學習新語言總是有點困難...我真的很喜歡way vuejs的作品,但需要更多的練習,讓我的頭... ...真的非常感謝,因爲它幫助了我很多!奇蹟般有效! – jaimyborgman

+0

你更歡迎Jaimy!它是一個偉大的框架,一旦點擊了所以保持它,你將有一個偉大的工作知識,在任何時候:) –

0

由於您使用的一個模態分量,並試圖基於特定的按鈕,點擊表格改變其內容的mounted掛鉤只會當組件最初安裝火一次。

你想要的是內容每次顯示模態時都要更新。

首先,它看起來像你的組件只需要一個email道具。移動道具的剩餘部分將在該組件的data方法,因爲(我假設),他們沒有被傳遞到組件:

props: ['email'], 
data: function() { 
    return { 
    token: null, 
    logs: null, 
    expires: null, 
    } 
} 

然後,我會創建一個名爲fetchData新方法把$http.get呼叫:

fetchData: function() { 
    this.$http.get('http://localhost:2000/system/invites/' + this.email + '/details') 
    .then(response => { 
     this.update(response.body); 
    }, response => { 
     console.log('whoops something went wrong'); 
    }); 
} 

在你的模態分量的mounted鉤,使用jQuery一個監聽器添加到自舉模式的show事件。而且一定要刪除監聽器組件的beforeDestroy掛鉤:現在

mounted() { 
    $(this.$el).on('shown.bs.modal', this.fetchData); 
}, 
beforeDestroy() { 
    $(this.$el).off('shown.bs.modal', this.fetchData); 
} 

,每個模態的show事件觸發時,$http.get請求將觸發基於組件的email屬性的當前值。

Here's an example fiddle.

+0

感謝您的解釋,但我仍然有模態不會更新它的內容的問題...我已經更新了我的第一條消息,現在我已經有了完整的代碼 – jaimyborgman

+0

@jaimyborgman顯然,jQuery是必需的聽自舉事件。我已經更新了我的答案 – thanksd

+0

mmm仍然沒有更新...它看起來像beforeDestroy掛鉤不會被調用,如果我在那裏設置一個console.log()... – jaimyborgman