Vuex 是什么?
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。
vuex 應(yīng)用場(chǎng)景:
頻繁進(jìn)行數(shù)據(jù)交互,數(shù)據(jù)較多時(shí)(數(shù)據(jù) 和 組件 分離,分別處理,那么使用 Vuex 是非常合適的)
Vuex的工作流程
首先通過dispatch提交一個(gè)action
在action中我們可以執(zhí)行一些異步的操作,或者根據(jù)不同的情況分發(fā)不同的mutation
接著在action中調(diào)用commit,觸發(fā)一個(gè)mutation
所有修改state的操作,全部應(yīng)該放在mutation中來做
而state更新之后,會(huì)調(diào)用Vue的底層方法,通知視圖進(jìn)行更新渲染
Vuex的核心屬性及使用
state
state存儲(chǔ)了Vuex的基本數(shù)據(jù),在state中存儲(chǔ)的數(shù)據(jù)都是經(jīng)過Vue底層watcher偵聽的數(shù)據(jù),可以實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)
actions
actions存放了Vuex中所有的異步操作,可以在actions中通過commit分發(fā)不同的mutation,在不同的情況下執(zhí)行不同的方法
mutations
mutations存放了Vuex中所有關(guān)于state的操作,修改state只能通過mutations,否則的話數(shù)據(jù)不會(huì)響應(yīng)式更新
getters
getters就類似與Vue實(shí)例中的computed,計(jì)算屬性,所有關(guān)于數(shù)據(jù)的復(fù)雜計(jì)算應(yīng)該放在getters中來操作
modules
modules,類似于redux中的reducer,每一個(gè)module都擁有自己的state、mutations、actions、getters;將整個(gè)store根據(jù)功能或者數(shù)據(jù)分解成不同的模塊,最后合并在一個(gè)Store中
使用步驟:
? ? 1.在vue項(xiàng)目 安裝:cnpm install vuex --save
? ? 2.在src文件夾中新建文件夾store, store文件夾中建立index.js
? ? ? ? import Vue from "vue"
? ? ? ? import Vuex from "vuex"
? ? ? ? Vue.use(Vuex)
? ? ? ? ?export default new Vuex.Store({
? ? ? ? ? ? ?state:{
? ? ? ? ? ? ? ?list:[];??
????????????},
? ? ? ? ? ? ? mutations:{},
? ? ? ? ? ? ?actions:{},
? ? ? ? ? ? ? getters:{},?
? ? ? ? ? ? ? modules:{}
? ? ? ? ? ?})
? ? 3.在main.js中
? ? ? ? import store from "./store/index"
? ? ? ? new Vue({
? ? ? ? ? ? ? ? ?store
? ? ? ? })
? ? 4.在一個(gè)組件中觸發(fā)
? ? ? ? ? ? ? ?import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
? ? ? ? ? ? ? ?export default {
????????????????????????name: 'App',
? ???????????????????? computed:{
? ? ? ????????????????????????????????...mapState(['list']),
? ? ? ????????????????????????????????...mapGetters([''])
? ???????????????????? }
????????????????}
或者? ? 使用:$store.state.list? ? ??
輔助函數(shù)mapState將state映射到計(jì)算屬性中去? ? ? ? ? ...mapState(["num",]),
輔助函數(shù)mapMutations直接將觸發(fā)函數(shù)映射到methods上? ? ? ? ? ? ?...mapMutations(["add"])
輔助函數(shù)mapGetters將其映射到本地計(jì)算屬性中去? ? ? ? ? ?...mapGetters(["setAdd"])
輔助函數(shù)mapActions直接將觸發(fā)函數(shù)映射到methods上? ? ? ? ?...mapActions(["add"])
... 擴(kuò)展運(yùn)算符
不用 vuex 會(huì)帶來什么問題
可維護(hù)性會(huì)下降,你要修改數(shù)據(jù),你得維護(hù) 3 個(gè)地方
可讀性下降,因?yàn)橐粋€(gè)組件里的數(shù)據(jù),你根本就看不出來是從哪里來的
增加耦合,大量的上傳派發(fā),會(huì)讓耦合性大大的增加,本來 Vue 用 Component 就是為了減少耦合,現(xiàn)在這么用,和組件化的初衷相背
vuex 原理: 常問
vuex 僅僅是作為 vue 的一個(gè)插件而存在,不像 Redux,MobX 等庫可以應(yīng)用于所有框架,vuex 只能使用在 vue 上,很大的程度是因?yàn)槠涓叨纫蕾囉?vue 的 computed 依賴檢測(cè)系統(tǒng)以及其插件系統(tǒng),vuex 整體思想誕生于 flux,可其的實(shí)現(xiàn)方式完完全全的使用了 vue 自身的響應(yīng)式設(shè)計(jì),依賴監(jiān)聽、依賴收集都屬于 vue 對(duì)對(duì)象 Property set get 方法的代理劫持。
最后一句話結(jié)束 vuex 工作原理,vuex 中的 store 本質(zhì)就是沒有 template 的隱藏著的 vue 組件;
使用 Vuex 只需執(zhí)行 Vue.use(Vuex),并在 Vue 的配置中傳入一個(gè) store 對(duì)象的示例,store 是如何實(shí)現(xiàn)注入的?美團(tuán)
Vue.use(Vuex) 方法執(zhí)行的是 install 方法,它實(shí)現(xiàn)了 Vue 實(shí)例對(duì)象的 init 方法封裝和注入,使傳入的 store 對(duì)象被設(shè)置到 Vue 上下文環(huán)境的store中。
因此在VueComponent任意地方都能夠通過this.store 訪問到該 store。
state 內(nèi)部支持模塊配置和模塊嵌套,如何實(shí)現(xiàn)的?--美團(tuán)
在 store 構(gòu)造方法中有 makeLocalContext 方法,所有 module 都會(huì)有一個(gè) local context,根據(jù)配置時(shí)的 path 進(jìn)行匹配。
所以執(zhí)行如 dispatch('submitOrder', payload)這類 action 時(shí),默認(rèn)的拿到都是 module 的 local state,如果要訪問最外層或者是其他 module 的 state,
只能從 rootState 按照 path 路徑逐步進(jìn)行訪問。
在執(zhí)行 dispatch 觸發(fā) action(commit 同理)的時(shí)候,只需傳入(type, payload),action 執(zhí)行函數(shù)中第一個(gè)參數(shù) store 從哪里獲取的?美團(tuán)
store 初始化時(shí),所有配置的 action 和 mutation 以及 getters 均被封裝過。在執(zhí)行如 dispatch('submitOrder', payload)的時(shí)候,
actions 中 type 為 submitOrder 的所有處理方法都是被封裝后的,其第一個(gè)參數(shù)為當(dāng)前的 store 對(duì)象,所以能夠獲取到 { dispatch, commit, state, rootState } 等數(shù)據(jù)。
Vuex 如何區(qū)分 state 是外部直接修改,還是通過 mutation 方法修改的?--美團(tuán)
Vuex 中修改 state 的唯一渠道就是執(zhí)行 commit('xx', payload) 方法,其底層通過執(zhí)行 this._withCommit(fn) 設(shè)置_committing 標(biāo)志變量為 true,
然后才能修改 state,修改完畢還需要還原_committing 變量。外部修改雖然能夠直接修改 state,但是并沒有修改_committing 標(biāo)志位,
所以只要 watch 一下 state,state change 時(shí)判斷是否_committing 值為 true,即可判斷修改的合法性。
調(diào)試時(shí)的"時(shí)空穿梭"功能是如何實(shí)現(xiàn)的?--美團(tuán)
devtoolPlugin 中提供了此功能。因?yàn)?dev 模式下所有的 state change 都會(huì)被記錄下來,'時(shí)空穿梭' 功能其實(shí)就是將當(dāng)前的 state 替換為記錄中某個(gè)時(shí)刻的 state 狀態(tài),
利用 store.replaceState(targetState) 方法將執(zhí)行 this._vm.state = state 實(shí)現(xiàn)。