拆分元件後的資料獨立,好處是彼此不會受影響,只要關注於元件本身即可,但有時候還是需要向外傳遞資料,這時就可以使用 emit 來處理。
練習範例 - 資料傳遞至父層
點擊子層的按鈕,將累加的資料傳遞到父層來顯示。
首先先確認在 Vue 的物件實體中是否能實作這個功能,h2
下方加上一個按鈕。
HTML
1 2 3 4 5 6 7 8 9
| <div id="app"> <h2>透過 emit 向外傳遞資訊</h2> 我透過元件儲值了 {{ cash }} 元 <button class="btn btn-primary">click</button>
<button-counter></button-counter> <hr /> <button-counter></button-counter> </div>
|
局部元件與 Vue 實體
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <script type="text/x-template" id="buttonCounter"> <div> <button @click="incrementCounter" class="btn btn-outline-primary">增加 {{ counter }} 元</button> <input type="number" class="form-control mt-2" v-model="counter"> </div>` </script>
<script> Vue.component('buttonCounter', { template: `#buttonCounter`, data: function () { return { counter: 1 } }, methods: {
} });
var app = new Vue({ el: '#app', data: { cash: 300 }, methods: {
} }); </script>
|
觸發事件
在 HTML 中要用 button
來觸發事件,使用 v-on:click
,並在 methods
中建立方法屬性與要執行的內容。
HTML
建立點擊事件。
1 2 3 4 5 6 7 8 9
| <div id="app"> <h2>透過 emit 向外傳遞資訊</h2> 我透過元件儲值了 {{ cash }} 元 <button @click="incrementTotal" class="btn btn-primary">click</button>
<button-counter @click="incrementTotal"></button-counter> <hr /> <button-counter></button-counter> </div>
|
Vue
將對應的方法寫入 methods
。
1 2 3 4 5 6 7 8 9 10 11
| var app = new Vue({ el: "#app", data: { cash: 300, }, methods: { incrementTotal() { this.cash += 1; }, }, });
|
於局部元件註冊點擊事件
確認可以實作累加功能後,在局部元件加入點擊事件,並且啟用上方寫好的 incrementTotal
的方法內容,於局部元件的 vue 物件中寫入該屬性。
HTML
1 2 3 4 5 6 7 8
| <div id="app"> <h2>透過 emit 向外傳遞資訊</h2> 我透過元件儲值了 {{ cash }} 元 <button @click="incrementTotal" class="btn btn-primary">click</button> <button-counter @increment="incrementTotal"></button-counter> <hr /> <button-counter></button-counter> </div>
|
局部元件
1 2 3 4 5 6
| <script type="text/x-template" id="buttonCounter"> <div> <button @click="incrementCounter" class="btn btn-outline-primary">增加 {{ counter }} 元</button> <input type="number" class="form-control mt-2" v-model="counter"> </div>` </script>
|
Vue
於局部元件內的方法,透過 $emit()
的方式將可以觸發父層的 @click="incrementTotal"
點擊事件,emit
前面要加一個 $
字號,裡面帶入局部元件的事件名稱(此名稱可自訂)
1 2 3 4 5 6 7 8 9 10 11 12 13
| Vue.component("buttonCounter", { template: `#buttonCounter`, data: function () { return { counter: 1, }; }, methods: { incrementCounter() { this.$emit("increment"); }, }, });
|
就完成點擊內部元件觸發外層事件,讓數字可以往上壘加。
emit
是可以傳遞參數的,其參數就是 this.counter
,也就是局部元件中的 counter 的值。
1 2 3 4 5
| data: function () { return { counter: 1 } }
|
但為了確保傳入的值為數字型別,所以外面使用 Number 將 this.counter 包起來。
1 2 3 4 5
| methods: { incrementCounter(){ this.$emit('increment'Number(this.counter)); } }
|
改寫 Vue 物件實體
如果在另一個按鈕要改變輸入的值,並將其值累加於父層上,在 Vue 物件實體的方法中,帶入參數 newNumber,在將原本累加的程式碼改寫成下方程式碼,就可以完成在子層設定的值,累加到父層上。
1 2 3 4 5 6 7 8 9 10 11
| var app = new Vue({ el: "#app", data: { cash: 300, }, methods: { incrementTotal(newNumber) { this.cash = this.cash + newNumber; }, }, });
|