首先我們先拋出三個問題
(1)有了vuex我們是不是就不需要組件之間傳參?
(2)vuex和localstorage啥區(qū)別?
(3)vuex里面直接修改state為什么還要有專門的修改方法mutation?
先把3個問題的答案放出來:
(1)vuex是多個組件,共享同一個數(shù)據(jù)的狀態(tài)管理工具。只是父子之間的數(shù)據(jù)傳遞沒必要使用vuex,小型項目官方都不推薦使用vuex,只會增加項目的負(fù)擔(dān),大型的項目并且是多個組件共享的用vuex更好
(2)vuex和localstorage兩者應(yīng)用場景不同。vuex是當(dāng)前vue項目的全局狀態(tài)對象,存放在內(nèi)存中,一旦當(dāng)前vue項目刷新,vuex的數(shù)據(jù)也將恢復(fù)默認(rèn)值;而localstorage是存放在瀏覽器中的對象,即使刷新數(shù)據(jù)也仍然存在。
(3)對于這個問題,在創(chuàng)建 store 的時候傳入 strict: true, 開啟嚴(yán)格模式,那么任何修改state的操作,只要不經(jīng)過mutation的函數(shù),vue就會 throw error
const store = new Vuex.Store({
state,
strict:true
//開啟嚴(yán)格模式后,只能通過mutation來改變狀態(tài)(不支持異步)否則會報錯
})
//下面的開啟嚴(yán)格模式就會報錯,不開啟是可行的
console.log(store.state.count) //0
store.state.count = 3;
console.log(store.state.count) //3
注意:發(fā)布環(huán)境下不要開啟嚴(yán)格模式,嚴(yán)格模式會深度監(jiān)測狀態(tài)樹來檢測不合規(guī)的狀態(tài)變化,造成不必要的性能損失
但是真正原因是:
Vuex的state是響應(yīng)式的,響應(yīng)式就是狀態(tài)改變頁面組件也實時更新。但是要實現(xiàn)響應(yīng)式必須通過提交mutation去改變state,并且還需要遵守一定的規(guī)則

下面從是什么,為什么,怎么用的角度來談對vuex的理解
【1】vuex是什么
多個組件,共享,同一個數(shù)據(jù)的狀態(tài)管理工具
vuex適用于大型單頁應(yīng)用,簡單的應(yīng)用使用 Vuex 可能是繁瑣冗余的
【2】為什么
當(dāng)在開發(fā)大型單頁應(yīng)用時,會出現(xiàn)多個視圖組件依賴同一個狀態(tài),來自不同視圖的行為需要變更同一個狀態(tài)。如登錄狀態(tài)、加入購物車、音樂播放等。
或許你認(rèn)為可以用傳參的方法解決組件之間互相傳值的問題。但是傳參的方法對于多層嵌套的組件將會變得很繁瑣,并且對于兄弟組件間的傳遞無能為力。所以vuex出現(xiàn)了,相當(dāng)于一個“前端的數(shù)據(jù)庫”。
Vuex主要用于解決組件之間同一狀態(tài)的共享問題,它能把組件的共享狀態(tài)抽取出來,當(dāng)做一個全局單例模式進(jìn)行管理。 這樣不管你在何處改變狀態(tài),都會通知使用該狀態(tài)的組件做出相應(yīng)修改。即Vuex采用集中式存儲管理應(yīng)用的所有組件的狀態(tài) 這里的關(guān)鍵在于集中式存儲管理。 這意味著本來需要共享狀態(tài)的更新是需要組件之間的通訊,而現(xiàn)在有了Vuex,組件就都和store通訊了
【3】怎么用
安裝使用步驟
1.安裝
sudo cnpm install vuex -S
2.引入狀態(tài)管理工具vuex
import vuex from 'vuex'
import store from './vuex/store'
3.main.js里面實例化
new Vue({
el: '#app',
router, :style="{ 'left': leftnum + 'px' }"
store,
components: { App },
template: '<App/>'
})
4.在src里面和views同級創(chuàng)建vuex文件里面store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 定義狀態(tài)
state: {
//動態(tài)路由的數(shù)組
keepAlive:[],
//全局域名
domainName:"",
}
})
export default store
5.使用:this.$store.state.名字
使用方法核心內(nèi)容
(1)state 存放狀態(tài)
(2)mutations 美[mju??tion] 同步的,唯一更改state的方法是提交 mutation。
(3)getters 加工state成員給外界類似于計算屬性
(4)actions 異步的,然后提交mutation去操作state
(5)modules 模塊化狀態(tài)管理

(1)state 存放狀態(tài)
const store = new Vuex.store({
state:{
name:'jack'
},
})
//頁面調(diào)用
this.$store.state
(2)mutations同步的對state操作的集合,比如對該數(shù)據(jù)的修改、增加、刪除等等。里面的函數(shù)有兩個默認(rèn)形參([state] [payload])
state是當(dāng)前VueX對象中的state
payload是該方法在被調(diào)用時傳遞參數(shù)使用的
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
state:{
name:'jack'
},
mutations:{
//es6語法,等同edit:funcion(){...}
//編輯
edit(state,payload){
//(1)直接調(diào)用
state.name = 'wayne'
//(2)傳值調(diào)用
state.name = payload
//(3)傳值對象調(diào)用
state.name = payload.name
},
//新增
myadd(state,payload){
//新增邏輯
Vue.set(state,"name1","dawei")
},
//刪除
mydel(state,payload){
//刪除邏輯
Vue.delete(state,"name1")
},
}
})
export default store
//頁面通過this.$store.commit調(diào)用
//(1)直接調(diào)用
this.$store.commit('edit')
//(2)傳值調(diào)用
this.$store.commit('edit','wayne')
//(3)傳值對象調(diào)用
this.$store.commit('edit',{name:'wayne',sex:'男'})
//還可以這么寫
this.$store.commit({
type:'edit',
payload:{
name:'wayne',
sex:'男'
}
})

新增和刪除不能使用xx.xx = xx,delete state.info.age這種原來的模式因為不是響應(yīng)式的,響應(yīng)式規(guī)定新增和刪除有自己的方法,這樣才能自動更新到組件上面去;
新增用Vue.set(state,"name1","dawei"),
刪除用Vue.delete(state,"name1")
(3)getters 加工state成員給外界類似于計算屬性
可以對state中的成員加工后傳遞給外界,Getters中的方法有兩個默認(rèn)參數(shù)
state 當(dāng)前VueX對象中的狀態(tài)對象
getters 當(dāng)前getters對象
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
state:{
name:'jack',
age:'15'
},
mutations:{
//編輯
edit(state,payload){
}
},
getters:{
nameInfo(state){
return "姓名:"+state.name
},
fullInfo(state,getters){
return getters.nameInfo+'年齡:'+state.age
}
}
})
export default store
// 調(diào)用
this.$store.getters.fullInfo//姓名:jack 年齡:15
(4)actions 專門放置異步操作,然后提交mutation去操作state
注意:Action 提交的是 mutation,而不是直接改變state,只有mutation能改變state。
至于是在頁面組件中等異步操作(如axious請求接口改變state)完成后去commit調(diào)用mutation;還是直接action去做異步axious,根據(jù)不同的業(yè)務(wù)場景有不同的選擇,也有不同的好處體現(xiàn)出來。
比如多次遇到的異步(如axious請求接口改變state)那就直接放在action里面,需要的時候頁面組件直接使用this.$store.dispatch就可以不用重復(fù)寫axious,所以vuex只是為了更靈活使開發(fā)者多一個選擇,讓代碼盡可能的變動優(yōu)雅。
Actions中的方法有兩個默認(rèn)參數(shù)
context 上下文(相當(dāng)于箭頭函數(shù)中的this)對象
payload 掛載參數(shù)
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
state:{
name:'jack'
},
mutations:{
//es6語法,等同edit:funcion(){...}
//編輯
edit(state,payload){
//(2)傳值調(diào)用
state.name = payload
}
},
actions:{
Edit(context,payload){
//異步操作
setTimeout(()=>{
//提交mutations方法,修改state
context.commit('edit',payload)
},2000)
}
}
})
export default store
//在頁面組件中調(diào)用:
this.$store.dispatch('Edit','wayne')
(5)modules 模塊化狀態(tài)管理
當(dāng)項目龐大,狀態(tài)非常多時,可以采用模塊化管理模式。Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割。
const store = new Vuex.Store({
models:{
a:{
state:{},
getters:{},
....
},
b:{
state:{},
getters:{},
....
},
}
})
//調(diào)用
this.$store.state.a
//而提交或者dispatch某個方法和以前一樣,會自動執(zhí)行所有模塊內(nèi)的對應(yīng)type的方法:
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')