Vue入門系列(五)組件通信

組件內通信主要分為兩種:父子組件通信和子組件之間通信。

1.父子組件通信

  • 父組件通過props屬性向子組件傳遞數據,這點和React一樣。
  • 子組件通過事件emit給父組件發送消息。
props-events.png

看一個例子:

// 組件A中使用子組件confirmDialog
<template>
...
  <vc-confirmDialog :msgTitle="msgObj.title" :msgBody="msgObj.msg" 
    v-on:cancel="closeDialog" v-on:ok="deleteItem">
  </vc-confirmDialog>
</template>
<script type="es6">
  import confirmDialog from '../widget/confirmDialog.vue';
  export default{
    ...
    components: {
      'vc-confirmDialog': confirmDialog //定義組件標簽
    },
}
</script>

//子組件confirmDialog
<script type="es6">
  export default{
  ...
  // 接收父組件的屬性值
  props: {
            msgTitle: {
                type: String,
                default: ''
            },
            msgBody: {
                type: String,
                default: ''
            }
        }
  },
  methods: {
            cancel: function () {
                // 觸發父組件屬性函數
                this.$emit('cancel');
            },

            ok: function () {
                // 觸發父組件屬性函數
                this.$emit('ok');
            }
        }
  }
</script>

父組件通過屬性綁定方式<vc-confirmDialog :msgTitle="msgObj.title" :msgBody="msgObj.msg" @cancel="closeDialog" @ok="deleteItem"></vc-confirmDialog>傳遞了兩類屬性參數給子組件:

  1. 數據屬性:msgTitlemsgBody是傳遞給子組件的數據,子組件通過props接收。
  2. 事件屬性:父組件通過@eventName="eventFuc"來定義接收函數,一旦子組件觸發需要父組件同步更新的事件$emit("eventName"),父組件即會調用eventFunc,然后更新數據。

父組件可以利用ref屬性直接訪問組件實例/DOM對象。這一點,和React一樣。

<vc-confirmDialog :msgTitle="msgObj.title" :msgBody="msgObj.msg"
 @cancel="closeDialog" @ok="deleteItem" ref="dialog"></vc-confirmDialog>
...
//父組件直接調用子組件方法
this.$refs.dialog.ok();

相比Vue,React父子組件通信無需事件機制,只需要屬性傳遞即可(參考文章:React入門系列(六)組件間通信)。

2.組件間通信

我們可以定義一個空的Vue實例作為event bus,通過事件廣播emit和事件監聽on來傳遞數據。

// 數據總線bus.js
import Vue from 'vue';
export default new Vue();

// 組件A中觸發事件
bus.$emit('toggleLogin', false);

// 組件B中接收事件
bus.$on('toggleLoading', (show)=>{
  this.isShowLoading = show;
});

如果是大量組件交叉性復雜通信,建議用插件Vuex處理。

3.Vuex

Vuex的核心是一個全局store,其為一個容器,包含著應用中大部分的狀態(state)
Vuex 和單純的全局對象有以下兩點不同:

  • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。

  • 不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交(commit) mutations。

vuex.png
(1) state

Vuex 使用 單一狀態樹 —— 用一個對象就包含了全部的應用層級狀態。

這也意味著,每個應用將僅僅包含一個 store 實例(可以利用modules把store細分)。

vue組件內調用:

this.$store.state.count

也可以通過輔助函數mapState獲取多個狀態值。

export default {
  computed: mapState({
    count: state => state.count,
    countAliasName: 'count',
    totalCount (state) {
      return state.count + this.localCount
    }
  })
}

如果計算屬性名與state節點屬性名稱一直,那么,可以通過數組方式更加便捷的獲取state節點。
如果mapState的值和其他計算屬性混合使用,那么,利用ES的對象展開運算符吧。

computed: {
  //  獲取 store.state.count
  ...mapState(["count"]),
  others
}
(2) Getter

Getter可以認為是store上的計算屬性,它的返回值會根據依賴被緩存起來,只有當依賴值發生了變化,才會被重新計算。

state: {
    todos: [
      { id: 1, text: 'abc', checked: true },
    ]
  },
getters: {
    checkedTodos: state => {
      return state.todos.filter(todo => todo.checked)
    }
  }

組件中使用getter如下:

computed: {
  checkedTodosCount () {
    return this.$store.getters.checkedTodos.length
  }
}

如果組件需要批量使用多個getter函數,那么,可以通過輔助函數mapGettersgetter混入到computed對象中。

export default {
  computed: {
    ...mapGetters(['checkedTodosCount'])
  }
}
(3) moutation

mutation 非常類似事件:每個 mutation 都有一個字符串的事件類型 (type) 和 一個 回調函數 (handler)。

  • mutation 必須是同步函數
  • 提交mutation需要用commit函數
mutations: {
  //payload就是額外的參數
  increment (state, payload) {
    state.count += payload.amount;
  }
}
組件內觸發事件:
// 以載荷形式分發
this.$store.commit('increment',{count: 10}); 或者
// 以對象形式分發
this.$store.commit({
  type: 'increment',
  count: 10
})

也可以使用輔助函數mapMutations將多個store.commit映射到method對象上。

export default {
  methods: {
    ...mapMutations([
      'increment', // 等價于`this.$store.commit('increment')`
    ]),
  }
}
(4) actions

與mutations不同之處:

  • Action 提交的是 mutation。
  • Action 可以包含異步操作。
  • 提交Action需要用dispatch函數
actions: {
  increment ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}
組件內觸發事件:
this.$store.dispatch('increment');

同樣的,可以利用輔助函數mapActions將組件的methods 映射為 store.dispatch 調用。

export default {
  methods: {
    ...mapActions([
      'increment', // 等價于`this.$store.dispatch('increment')`
  }
}
(5) modules

使用單一狀態樹,導致應用的所有狀態集中到一個很大的對象。但是,當應用變得很大時,store 對象會變得臃腫不堪。

為了解決以上問題,Vuex 允許將 store 分割到模塊(module)。每個模塊擁有自己的 state,mutation,action。

modules.png
// modules/index.js如下
import knowledge from './knowledge'
import common from './common'
import demo from './demo'
import help from './help'

export default {
  knowledge,
  common,
  demo,
  help
}
// index.js 如下
import modules from "./modules";
export default new Vuex.Store({
  modules,
});
// 組件內使用如下
store.state.help
store.state.demo
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容