iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 27
0
Modern Web

Déjà-vu ? 要 Vue 過才知道系列 第 27

子元件向父元件傳值與訊息

  • 分享至 

  • xImage
  •  

人類溝通需要技巧,程式語言靠的是方法。

我們除了可以透過 Props 來讓父元件傳值給子元件外,也可以透過子元件向父元件傳遞訊息,並可以直接在子元件中操控父元件裡的資料。

在父元件傳值給子元件所使用的 Props ,在傳遞資料時是單向資料流(One-Way Data Flow),也就是說,只允許子元件向父元件傳遞資料,而不允許子元件直接操控 Props 裡的資料。有這個原則的原因是因為如果直接讓子元件直接操控 Props 裡的資料,資料的控制邏輯會變的很複雜與雜亂。單向資料流還是比較容易理解,Vue 也較推薦單向資料流的用法。雖然可以做到雙向但 Vue 不建議使用雙向。

那麼在 Vue 如何透過自定義事件向父元件傳遞訊息呢?即是使用 Vue 的內建$emit()方法。

子元件透過自定義事件向父元件傳遞訊息

語法:<button v-on:click="$emit('enlarge-text')>Enlarge Text</button>
說明:一個子元件裡的按鈕,點擊時會觸發一個特定的方法$emit(),並帶上一個參數,此參數為自定義的事件名稱enlarge-text,這個事件會傳遞給父元件,所以父元件會去監聽這個事件。

父元件中監聽子元件的事件

語法:<menu-item v-on:enlarge-text="fontSize += 0.1"></menu-item>
說明:v-on:enlarge-text為綁定事件名稱,fontSize += 0.1則為事件對應的處理邏輯。

透過實作的情境會比較清楚傳遞的運作原理:
實作範例效果:在子元件中點擊Enlarge Text按鈕之後,會控制父元件中的parentsMsg使文字有大小變化。

  1. 在父元件的 HTML template 插入我們在data的屬性parentsMsg內容為'Hello, is parentsMsg',為控制目標。
  2. 在子元件的樣版template裡加上按鈕綁定監聽事件,並以$emit()方法,帶上指定的自定義事件參數。
  3. 在父元件的 HTML template 綁定剛剛的自定義事件參數
  4. 在父元件的methods增加方法handleSize,每按一次按鈕增加字體大小 5px,並在 data 裡增加屬性fontSize: 12,預設值。
  5. 在父元件的 HTML template 的插入值parentsMsg 元素上綁定元素的字體大小,記得要加入字體單位px
<!-- 父元件的HTML -->
<div id="app">
  <menu-item @enlarge-text="handleBiggerSize"></menu-item>
</div>
<script>
// 子元件 使用$emit()傳遞
Vue.component('menu-item',{
  template: `
    <div>
      <div >{{parentsMsg}}</div>
      <button @click="$emit('enlarge-text')">放大父元件中元素的字體大小</button>
    </div>
  `
})
// 父元件
const vm= new Vue({
  el:'#app',
  data:{
    parentsMsg: 'Hello, is parentsMsg',
    fontSize: 16,
  },
  methods:{
    handleBiggerSize: function(){
      // 字體變大
      this.fontSize += 5
    },
  }
})
</script>

子元件向父元件傳值

我們也可以直接在$emit()裡以第二個參數帶值進去,就不需要每次去父元件的方法裡修改。
子元件透過自定義事件向父元件傳遞訊息+帶值
語法:<button v-on:click="$emit('enlarge-text',0.1)>Enlarge Text</button>
說明:一個子元件裡的按鈕,點擊時會觸發一個特定的方法$emit(),並帶上兩個參數,第一參數為自定義的事件名稱enlarge-text,第二參數是值,個事件和值會直接傳給父元件,所以父元件會去監聽這個事件。

父元件中監聽子元件的事件

接收語法:<menu-item v-on:enlarge-text+= $event"></menu-item>
說明:v-on:enlarge-text為綁定事件名稱,fontSize += $event則為事件對應的處理邏輯會對應到子主件的綁定方法的第二參數值,$event是固定的寫法。

當按下子元件的模版template裡的按鈕,會直接取到第二參數作為放大字體的增加單位。

實作範例效果:

<!-- 父元件的HTML -->
<div id="app">
  <menu-item @minify-text="handleMinifySize($event)"></menu-item>
</div>
<script>
// 子元件 使用$emit()傳遞
Vue.component('menu-item',{
  template: `
    <div>
      <div >{{parentsMsg}}</div>
      <button @click="$emit('minify-text',5)">縮小父元件中元素的字體大小</button>
    </div>
  `
})
// 父元件
const vm= new Vue({
  el:'#app',
  data:{
    parentsMsg: 'Hello, is parentsMsg',
    fontSize: 16,
  },
  methods:{
    handleMinifySize: function(value){
      // 字體變大
      this.fontSize -= value
    }
  }
})
</script>

每日一句法文有益身心:Je suis fatigué ! --> 者.雖.發踢給! --> 我好累啊!


上一篇
Vue 元件傳遞資料的命名坑與型別
下一篇
Vue Components 子元件之間的資料傳遞
系列文
Déjà-vu ? 要 Vue 過才知道30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言