在使用 Vue 框架作單頁面應用時,咱們時常會遇到傳值,組件公用狀態的問題。(子父間傳值文章傳送門) ,若是是簡單的應用,兄弟組件之間通訊還能使用 eventBus 來做爲中介。可是一旦應用比較龐大,那狀態將會變得難以維持管理。git
Vue 爲咱們提供了進行大型狀態管理的 Vuex,相似 Flux 。Vuex 採用了集中式存儲管理全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。github
直接用官方文檔提供的關係圖來說:vuex
一個 store 中包含了: Actions( 行爲 ) 、Mutations( 突變 )、State( 狀態 ),完整的 Vuex 動做是這樣的 Components( 組件 )中 methods 裏面一個方法 dispatch (調用)Actions,Actions 而後 commit 對應的Mutations, 只有 Mutations 能夠操做 State 中的狀態數據,狀態一改變,組件中就從新渲染。路線:C——>A——>M——>S——>C。npm
(1)引入式app
<script src="/path/to/vue.js"></script> <script src="/path/to/vuex.js"></script>
(2)npm 安裝框架
npm install vuex --save
1、這邊提供兩中目錄結構共使用:函數
一、適合簡單的項目,全部模塊放到 store.js 中管理學習
import Vue from "vue" import Vuex from "vuex" Vue.use(Vuex) const store = new Vuex.Store({ state:{ count: 10, }, mutations:{ //格式:類型(名字)+處理函數 //加1 INCREMENT(state) { //console.log(state)//state對象 state.count++; } }, actions:{ increment({commit}){ commit("INCREMENT") } } }) export default store
二、將各個 js 單文件分開,便於管理ui
==store =index.js =mutations.js =actions.js =getters.js
index.js 主文件入口:
/** *主要入口文件,引入其餘四個js */ import Vue from "vue" import Vuex from "vuex" Vue.use(Vuex) //引入actions、mutations、getters import actions from "./actions.js" import mutations from "./mutations.js" import getters from "./getters.js" // 定義狀態state const state = { } // 設置暴露接口 export default new Vuex.Store({ state, mutations, actions, getters })
mutations.js 、actions.js 、getters.js 文件相似:
export default { //方法 對state數據進行統一操做 }
main.js 進行全局註冊:
import store from './store/index' /* eslint-disable no-new */ new Vue({ el: '#app', store, router, template: '<App/>', components: { App } })
2、結合簡易‘’不符合邏輯‘’計算器講解 Vuex
一、先上簡陋圖:
二、邏輯: 輸入框中進行數字輸入,加減乘除按鈕點擊使用,點擊確認輸出結果。
三、目錄結構:
*一 一對應
XTGL : 計算器
showBox : 最上方顯示區
input : 輸入區
calc : 四則運算區
output : 結果輸出區
四、代碼實現:
components 部分
inputBox.vue 負責初始值的輸入,dispatch actions 中的 inputevent ,爲了將輸入的值顯示到 showBox 中。
<template> <div class="inputBox"> <div class="layui-form-item"> <label class="layui-form-label">輸入:</label> <div class="layui-input-block"> <input class="layui-input" v-model="inputNum" @blur="inputEvent"> </div> </div> </div> </template> <script> export default { data () { return { inputNum: '', } }, methods:{ inputEvent:function(){ //調用dispatch this.$store.dispatch('inputevent',this.inputNum) } } } </script>
showBox.vue 只須要將 store.js 中 state 裏的初始值拿到並顯示,這邊 this.$store.state.inputNum
須要寫在 computed 中。
<template> <div class="showBox"> <div class="layui-form-item"> <div class="layui-input-block"> <input class="layui-input" v-model="inputNum"> </div> </div> </div> </template> <script> export default { data () { return { } }, computed:{ //拿inputNum inputNum () { return this.$store.state.inputNum } } } </script> <style scoped> .layui-input-block{ margin-left: 0!important; } .layui-input{ width: 100%!important; } </style>
calc.vue
<template> <div class="clacBox"> <div> <button class="btn layui-btn" @click="increment">加1</button> <button class="btn layui-btn" @click="decrement">減1</button> <button class="btn layui-btn" @click="increment">乘2</button> <button class="btn layui-btn" @click="increment">除2</button> </div> </div> </template> <script> export default { data () { return { } }, methods:{ increment () { //dispatch調用 this.$store.dispatch('increment') }, decrement () { this.$store.dispatch('decrement') } } } </script> <style scoped> </style>
outputBox.vue 點擊確認按鈕,操做 store.js 中 actions 中 resultevent, 而且拿到結果值 resultNum。
<template> <div class="inputBox"> <div class="layui-form-item"> <label class="layui-form-label">結果:</label> <div class="layui-input-inline"> <input class="layui-input" v-model="resultNum"> </div> </div> <button class="btn layui-btn layui-btn-danger" @click="resultEvent">確認</button> </div> </template> <script> import {mapState} from "vuex" export default { data () { return { } }, computed:{ resultNum () { return this.$store.state.resultNum } }, methods:{ resultEvent () { this.$store.dispatch('resultevent') } } } </script> <style scoped> .inputBox{ overflow: hidden; } .layui-form-item{ float: right; margin-top: 15px; } button{ float: right; margin-top: 15px; } </style>
XTGL.vue 父組件
<template> <div id="XTGLPage" class="XTGLPage"> <showBox></showBox> <inputBox></inputBox> <calcBox></calcBox> <outputBox></outputBox> </div> </template> <script> import showBox from "./chlidComponents/showBox.vue" import inputBox from "./chlidComponents/inputBox.vue" import calcBox from "./chlidComponents/calc.vue" import outputBox from "./chlidComponents/outputBox.vue" export default { name:'', data () { return { } }, components:{ inputBox, showBox, calcBox, outputBox } } </script> <style scoped> .XTGLPage{ width: 500px; height: 400px; padding: 30px 20px 0; border: 2px solid #ccc; box-shadow: 10 10 0 0 #333; background-color: #ccc; } </style>
store 中 store.js 部分 完整操做是 '自下往上'
import Vue from "vue" import Vuex from "vuex" Vue.use(Vuex) const store = new Vuex.Store({ state:{ inputNum:'', outputNum:'', resultNum:'' }, mutations:{ //格式:類型(名字)+處理函數 //大寫 //inputNum賦值 INPUTEVENT(state,value) { state.inputNum += value state.outputNum = value }, //加 INCREMENT(state,value) { state.inputNum += '+1' state.outputNum++ }, //減 DECREMENT(state,value) { state.inputNum += '-1' state.outputNum-- }, //結果 RESULTEVENT(state){ state.resultNum = state.outputNum console.log(state.resultNum) } }, actions:{ //小寫 inputevent({commit},value){ commit("INPUTEVENT",value) }, increment({commit},value){ commit("INCREMENT",value) }, decrement({commit},value){ commit("DECREMENT",value) }, resultevent({commit}){ commit("RESULTEVENT") } } }) export default store
代碼比較多,文字解釋待加入,先看效果圖:
操做複雜度,邏輯複雜度爲0,本身都尷尬的設計,但願對於學習、理解 Vuex 有些許幫助!