圖片描述# Vuex
在介紹 Vuex 以前,我先拋出一個問題,以下圖javascript
請原諒並忽略手繪圖的粗糙,主要描述的結構是:html
組件Avue
組件Bjava
組件B1git
組件B2github
組件Cvuex
組件C1app
組件C2this
如今的問題要解決是組件C1或者C2要和組件B1或B2通訊,前面有詳細講過 Vue 自己組件之間通訊的方法,最簡單的就是 $parent
和 $children
,若是不知道如何使用的請回到上面看 組件通訊spa
如今用 $parent
和 $children
來上面的問題:組件C1調用組件B2的方法
this.$parent.$parent.$children[0].$children[1].Event1()
代碼寫到這問題解決了,可是若是再多幾層的組件嵌套關係,又或者組件層級關係因需求發生了改變,那上面的代碼又得從新改變。
爲了解決這樣的問題,有人想到了把爲什麼不把全部組件的方法統一到一個公共對象,由於對象是一個無序屬性集合,並且仍是引用類型,而後把這個對象放到最外層,這樣無論組件嵌套多少級,都能調用到對應的方法。
那上面的案例就能夠生成以下面這種結構的對象了
var obj = { A: {}, B: {}, B1: { Event1: function(){}, Event2: function(){}, Event3: function(){} }, B2: { Event1: function(){}, Event2: function(){}, Event3: function(){} }, C: {}, C1: { Event1: function(){}, Event2: function(){}, Event3: function(){} }, C2: { Event1: function(){}, Event2: function(){}, Event3: function(){} }, }
場景:在組件 home 裏面使用組件 counter,在 home 組件中實現計數,在組件 counter 同步顯示當前計數。
export default { state: { count: 0 } }
<template> <div> <h3>count-{{common.state.count}}</h3> </div> </template> <script> import common from '../../common/common.js' export default { data(){ return { common } } } </script>
<template> <div> <fieldset> <legend><h3>home</h3></legend> <div> <input type="button" value="increment" @click="increment"/> <span>{{common.state.count}}</span> </div> </fieldset> <fieldset> <legend><h3>counter</h3></legend> <counter></counter> </fieldset> </div> </template> <script> import common from '../../common/common.js' import counter from '../counter/counter.vue' export default { data(){ return { common } }, components: { datagrid, counter }, methods: { increment(){ this.common.state.count += 1; } } } </script>
上面的案例是經過公共對象解決了簡單的跨組件通訊的問題,但若是組件 counter 也想能能夠實現計數,那最簡單的實現方法就是在組件 counter 當中也寫一個事件 increment,但這樣一來,事件就重複了。
封裝實現就是把事件 increment 也放到 common.js 對象中去,而後組件都調用這個公共的方法。
let state = { count: 0 } let mutations = { increment(){ state.count += 1; } } export default { state, mutations };
看似解決了問題,可是若是場景更復雜,組件層級更深,組件間要通訊的信息更多,組件間存在同名屬性同名方法但不一樣邏輯等,目前這種方法就解決不了,須要進行更深層次的封裝。
Vuex 就是上面這種解決方案的更深層次的實現。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) let state = { count: 0 } let mutations = { increment(){ state.count += 1; }, decrement(){ state.count -= 1; } } const store = new Vuex.Store({ state, mutations }) export default store
import Vue from 'vue' import store from './vuex/store' import homeComponent from './components/home/home.vue' new Vue({ el: '#app', store, render:h => h(homeComponent) })
<input type="button" value="increment" @click="increment"/> <span>{{$store.state.count}}</span> <script type="text/javascript"> methods: { increment(){ this.$store.commit('increment'); } } </script>
<span>{{$store.state.count}}</span>
this.$store.commit('increment');
觸發 mutations 的 increment 方法$store.state.count
獲取 store 的 state。