前端框架Vue(4)——vuex 狀態管理

一、Vuex 是什麼?

  Github vue-spa-demo 項目地址vue

  在使用 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

二、Vuex 安裝

(1)引入式app

<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>

(2)npm 安裝框架

npm install vuex --save

三、Vuex 使用,結合小實例

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 有些許幫助!

相關文章
相關標籤/搜索