[vue]初探vue生態核心插件Vuex

爲何會有 Vuex 這個東西 ?

現代前端框架主要解決的是 事件 -> 狀態 -> UI 將傳統前端在兩個過程的代碼剝離出來,變得更加容易維護;javascript

vue的聲明式渲染,解決了 狀態 和 UI 的同步問題,從而使咱們不須要因爲狀態發生改變去寫大量的命令式改變 dom 的代碼。html

而相似於 vuex 這類狀態管理的庫,則解決了 事件 -> 狀態 這個過程的維護問題。這類庫所作的事情就是管理從 事件源映射到狀態變化 這個過程(將這個映射過程從視圖組件中剝離出來,組織好這一部分的代碼,在組件外部進行狀態的管理)前端

具體表現就是一個全局的數據中心 store 配置,每一個組件進行更新的時候就通知數據中心,數據中心改變後,再去觸發每一個調用它的組件進行更新(這種更新是響應式的);幾個核心概念就是 mutations裏的方法能夠直接 mutatestore 中的狀態,而且 mutation 過程必須同步的,須要經過 commit 去觸發;而 actions 則容許異步的操做,經過 commit 去觸發 mutation ,達到間接修改 store的目的,action 自己須要經過 disptch去觸發。vue

Vuex與全局對象的區別

其實,vuex 與全局對象有必定的共同之處,那就是狀態會被全局共享,不管是嵌套多少組件…java

每個 Vuex 應用的核心就是 store(倉庫)。「store」基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有如下兩點不一樣:git

  1. Vuex 的狀態存儲是 響應式 的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地獲得 **高效更新 **。
  2. 你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交 (commit) mutation。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用。

Vuex常見的應用場景

管理狀態與共享狀態程序員

應用簡單時,可使用 propevent 來完成 父子組件 的通訊。使用 global event bus(event bus)來實現 簡單的非父子組件之間的跨組件 通訊。但對於 **多層級組件嵌套 **等較爲複雜的場景,使用 vuex 能更好地應對。(使用 event bus 的缺點是當狀態較複雜,調用組件很是多,要挨個依次通知全部組件更新;每一個組件對這個組件進行的狀態更新都要通知監聽該事件的全部組件;這樣會變得很是複雜)github

vuex 狀態管理模型,擁有一個統一的數據中心Store,Store用來維護狀態數據;每一個組件進行更新的時候就通知數據中心,數據中心改變後,再去觸發每個調用它的組件進行更新(至關於由數據中心來統籌狀態變化以及狀態變化的分發,而不是由每一個vue組件直接去操做state)vue-router

圖解圖解

vuex 是經過將 state 做爲數據中心,各個組件 共享 state 來實現跨組件通訊的, 此時的數據徹底獨立於組件。(點擊不一樣模塊的操做,再也不須要去發送亂七八糟的事件, 只是去調用事件中內心的 mutation 動做, 從而實現模塊間共享狀態的功能)vuex

須要構建一箇中大型單頁應用時,極可能會考慮如何更好地 在組件外部 管理狀態

vuex更多地用於解決 **跨組件通訊 **(多層嵌套組件之間的通訊問題)以及做爲 數據中心集中式存儲數據 (管理應用中錯綜複雜的狀態關係)

vuex 做爲數據存儲中心

vuexstate在單頁應用的開發中自己具備一個 數據庫 的做用,能夠將組件用到的數據存儲在 state中,並在 actions中封裝數據讀寫的邏輯。目前主要有兩種數據會使用 vuex進行管理

  1. 組件之間 全局共享 的數據
  2. 經過後端異步請求的數據

實際項目開發中更多的是用到第二種,即把經過後端異步請求的數據都歸入 vuex 狀態管理,在 actions 中封裝數據的增刪改查等邏輯,這樣能夠在必定程度上對前端的邏輯代碼進行分層,使組件中的代碼更多地關注頁面交互與數據渲染等 視圖層 的邏輯,而異步請求與狀態數據的持久化等則交由 vuex 管理

通常全局數據,會使用到 vuex 來管理。好比 用戶數據,系統數據 等,這些數據不少組件中都會使用,咱們固然能夠每次使用的時候都去請求,可是出於程序員的「潔癖」、「摳」等等優勢,仍是但願一次請求,處處使用。

這時候很天然的想到存儲在 localStorage 中,可是有個問題是,這些數據可能會變,若是沒能及時 同步 的話,就會用到不正確的數據,即便作了數據同步,可是 localStorage 中的數據不是響應式的,不能自動更新使用到這些數據的地方。這時候就想要開始使用 vuex了。

Vuex代碼的組織方式

vue-router 相似,有非模塊化寫法與模塊化寫法(其實不管何種寫法本質上是同樣的,目的就是導出一份 router或者 store 的配置數據)

以管理 count 與 用戶信息 userinfo 爲例,介紹 vuex代碼的組織方式

核心概念 state,getter,mutation,action,module

vuex 須要遵照的規則

應用層級的狀態應該集中到 單個 store 對象中

mutation是直接操做state的方法(惟一能改變狀態的方法),過程要求必須同步

action 經過commit去觸發mutation,從而間接修改狀態,優勢是容許異步邏輯,

非模塊化寫法
// 1.安裝 vuex

// 2.在入口文件中引入
// main.js
import Vuex from 'vuex'

// 3.Vue使用 vuex 插件
Vue.use(Vuex)

// 4.生成數據管理中心 store
const store = new Vuex.Store({
    state: {
        userinfonull// 須要給定初始值
        count: 0
    },
    // 直接經過mutation方法來mutate操做state; 只能以同步的方式; mutation方法須要經過commit來觸發
    mutations: {
        userinfofunction (state, payload{
              state.userinfo = options
            localStorage.userinfo = JSON.stringify(state.userinfo)
        },
        incrementfunction (state, payload{
            state.count += payload.amount
        }
    },
    // 經過commit觸發mutations裏的mutation方法, 以此間接修改 state; 容許異步操做;action方法須要經過dispatch來觸發
    actions: {
        incrementfunction (context, payload{
            context.commit('increment', payload)
        },
        incrementAsyncfunction (context{
            // 異步請求數據
            setTimeout(() => {
                var amount = 10// 模擬異步請求獲得數據
                context.commit('increment', { amount })
            }, 1000)
        },
        async userinfo (context) {
            let response = await getUserInfo() // 異步請求後端數據 方法須要 import
            if (response.ok) {
                let json = await response.json()
                context.commit('userinfo', json)
            }
        }
    },
    getters: {// 處理、過濾數據

    }
})

// 5.經過 store 配置參數注入狀態管理,從而任何組件可經過 this.$store 訪問狀態中心
new Vue({
    el'#app',
    store, // (*)
    render: function (h{
        return h(App)
    }
})
模塊化寫法
// 1.安裝vuex

// 2.引入
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
// import ...

// 3.Vue使用 vuex 插件
Vue.use(Vuex)

// 4.分模塊生成數據管理中心
// 配置 userinfo 狀態模塊 (還能再單獨拆出一個文件,而後import進來)
const moduleA = {
    state: {
        userinfonull // 須要初始化響應式數據
    },
    mutations: {
        userinfofunction (state, options{
            state.userinfo = options
            localstorage.userinfo = JSON.stringify(state.userinfo)
        }
    },
    actions: {
        async userinfo (context) {
            async userinfo (context) {
                let response = await response.json()
                if (response.ok) {
                    let json = await response.json()
                    context.commit('userinfo', json)
                }
            }
        },
        getters: {// 處理、過濾數據

        }
    }
}

// 配置 count 狀態模塊 (還能再單獨拆出一個文件,而後import進來)
const moduleB = {
    state: {
        count1,
    },
    mutations: {
        increment:function (state, payload{
            state.count += payload
        },
    },
    actions: {
        incrementfunction (context, payload{
              context.comit('increment', payload)  
        },
          incrementAsyncfunction (context{
            // 異步請求數據
            setTimeout(() => {
                var amount = 10// 模擬異步請求獲得數據
                context.commit('increment', { amount })
            }, 1000)
        },  
    },
    getters: {
        doubleCount (state) {
            return state.count * 2
        }
    }
}

// 5.導出一份 store 的配置
export default new Vuex.Store({
    modules: { // 這裏與非模塊化寫法有點不同;原來整個對象是一份配置...
        a: moduleA,
        b: moduleB,
    }
})

// store.state.a // -> moduleA 的狀態
// store.state.b // -> moduleB 的狀態

// 6.在根腳本 main.js 中引入 store 配置
import store from './store'
...
// 並經過 store 配置參數注入狀態管理,從而任何組件可經過 this.$store 訪問狀態中心
new Vue({
    el'#app',
    router,
    store,
    renderfunction (h{
        return h(App);
    }
});

在不一樣組件中使用或操做狀態

// 根組件
// App.vue
// 在生命週期中觸發全局共享數據的獲取
...
mounted () {
    if (!this.$store.state.userinfo) { // this.$store.state.a.userinfo 模塊化寫法的話
        this.$store.dispatch('userinfo')
    }
}

// 使用 state 的數據
computed: {
    userinfo () {
        return this.$store.state.userinfo
        // return this.$store.state.a.userinfo // 模塊化寫法的話
    },
    count () {
        return this.$store.state.count
        // return this.$store.state.b.count // 模塊化寫法的話
    }
}
// 子組件
// NavBar.vue
...
// 改變 state 的數據
methods: {
    // 使用 commit 觸發 mutations 中的 mutation 方法,直接修改 state 中的數據
    addOne () {
        this.$store.commit('increment', { amountthis.price })
    },
    // 使用 dispatch 觸發 actions 中的 action 方法;異步修改 state 中的數據
    addTenAsync () {
        this.$store.dispatch('incrementAsync')
    }
}

// 使用 state 的數據
computed: {
    userinfo () {
        return this.$store.state.userinfo
        // return this.$store.state.a.userinfo // 模塊化寫法的話
    }
}
// 路由頁面組件
// Manage.vue
...
// 改變 state 的數據
methods: {
    addTwo () {
        this.$store.commit('increment', { amountthis.price })
    }
}

// 使用 state 的數據
computed: {
    count () {
        return this.$store.state.count
        // return this.$store.state.b.count // 模塊化寫法的話
    }
},

總之,使用了 vuex 來管理狀態,點擊不一樣模塊的操做,再也不須要去發送亂七八糟的事件, 只是去調用事件中內心的 mutation 動做, 從而實現模塊間共享狀態的功能;修改一處,全局共享(不管是組件仍是路由頁面組件都能同步)

最後,再看看 vuex 官網的這張說明圖,是否是更加清晰了呢!

虛線綠框裏即vuex作的事虛線綠框裏即vuex作的事

-項目地址- vuex-demo

原文出處:https://www.cnblogs.com/rencoo/p/12049831.html

相關文章
相關標籤/搜索