首先我們先拋出三個(gè)問題
(1)有了vuex我們是不是就不需要組件之間傳參?
(2)vuex和localstorage啥區(qū)別擅编?
(3)vuex里面直接修改state為什么還要有專門的修改方法mutation?
先把3個(gè)問題的答案放出來:
(1)vuex是多個(gè)組件宪郊,共享同一個(gè)數(shù)據(jù)的狀態(tài)管理工具双炕。只是父子之間的數(shù)據(jù)傳遞沒必要使用vuex,小型項(xiàng)目官方都不推薦使用vuex,只會(huì)增加項(xiàng)目的負(fù)擔(dān),大型的項(xiàng)目并且是多個(gè)組件共享的用vuex更好
(2)vuex和localstorage兩者應(yīng)用場(chǎng)景不同。vuex是當(dāng)前vue項(xiàng)目的全局狀態(tài)對(duì)象火欧,存放在內(nèi)存中,一旦當(dāng)前vue項(xiàng)目刷新茎截,vuex的數(shù)據(jù)也將恢復(fù)默認(rèn)值苇侵;而localstorage是存放在瀏覽器中的對(duì)象,即使刷新數(shù)據(jù)也仍然存在企锌。
(3)對(duì)于這個(gè)問題榆浓,在創(chuàng)建 store 的時(shí)候傳入 strict: true, 開啟嚴(yán)格模式,那么任何修改state的操作撕攒,只要不經(jīng)過mutation的函數(shù)陡鹃,vue就會(huì) throw error
const store = new Vuex.Store({
state,
strict:true
//開啟嚴(yán)格模式后,只能通過mutation來改變狀態(tài)(不支持異步)否則會(huì)報(bào)錯(cuò)
})
//下面的開啟嚴(yán)格模式就會(huì)報(bào)錯(cuò)抖坪,不開啟是可行的
console.log(store.state.count) //0
store.state.count = 3;
console.log(store.state.count) //3
注意:發(fā)布環(huán)境下不要開啟嚴(yán)格模式萍鲸,嚴(yán)格模式會(huì)深度監(jiān)測(cè)狀態(tài)樹來檢測(cè)不合規(guī)的狀態(tài)變化,造成不必要的性能損失
但是真正原因是:
Vuex的state是響應(yīng)式的擦俐,響應(yīng)式就是狀態(tài)改變頁面組件也實(shí)時(shí)更新猿推。但是要實(shí)現(xiàn)響應(yīng)式必須通過提交mutation去改變state,并且還需要遵守一定的規(guī)則
下面從是什么,為什么蹬叭,怎么用的角度來談對(duì)vuex的理解
【1】vuex是什么
多個(gè)組件,共享状知,同一個(gè)數(shù)據(jù)的狀態(tài)管理工具
vuex適用于大型單頁應(yīng)用秽五,簡(jiǎn)單的應(yīng)用使用 Vuex 可能是繁瑣冗余的
【2】為什么
當(dāng)在開發(fā)大型單頁應(yīng)用時(shí),會(huì)出現(xiàn)多個(gè)視圖組件依賴同一個(gè)狀態(tài)饥悴,來自不同視圖的行為需要變更同一個(gè)狀態(tài)坦喘。如登錄狀態(tài)、加入購(gòu)物車西设、音樂播放等瓣铣。
或許你認(rèn)為可以用傳參的方法解決組件之間互相傳值的問題。但是傳參的方法對(duì)于多層嵌套的組件將會(huì)變得很繁瑣贷揽,并且對(duì)于兄弟組件間的傳遞無能為力棠笑。所以vuex出現(xiàn)了,相當(dāng)于一個(gè)“前端的數(shù)據(jù)庫”禽绪。
Vuex主要用于解決組件之間同一狀態(tài)的共享問題蓖救,它能把組件的共享狀態(tài)抽取出來,當(dāng)做一個(gè)全局單例模式進(jìn)行管理印屁。 這樣不管你在何處改變狀態(tài)循捺,都會(huì)通知使用該狀態(tài)的組件做出相應(yīng)修改。即Vuex采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài) 這里的關(guān)鍵在于集中式存儲(chǔ)管理雄人。 這意味著本來需要共享狀態(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里面實(shí)例化
new Vue({
el: '#app',
router, :style="{ 'left': leftnum + 'px' }"
store,
components: { App },
template: '<App/>'
})
4.在src里面和views同級(jí)創(chuàng)建vuex文件里面store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 定義狀態(tài)
state: {
//動(dòng)態(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成員給外界類似于計(jì)算屬性
(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同步的對(duì)state操作的集合珍坊,比如對(duì)該數(shù)據(jù)的修改牺勾、增加、刪除等等阵漏。里面的函數(shù)有兩個(gè)默認(rèn)形參([state] [payload])
state是當(dāng)前VueX對(duì)象中的state
payload是該方法在被調(diào)用時(shí)傳遞參數(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)傳值對(duì)象調(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)傳值對(duì)象調(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àn)椴皇琼憫?yīng)式的回还,響應(yīng)式規(guī)定新增和刪除有自己的方法,這樣才能自動(dòng)更新到組件上面去叹洲;
新增用Vue.set(state,"name1","dawei")柠硕,
刪除用Vue.delete(state,"name1")
(3)getters 加工state成員給外界類似于計(jì)算屬性
可以對(duì)state中的成員加工后傳遞給外界,Getters中的方法有兩個(gè)默認(rèn)參數(shù)
state 當(dāng)前VueX對(duì)象中的狀態(tài)對(duì)象
getters 當(dāng)前getters對(duì)象
//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請(qǐng)求接口改變state)完成后去commit調(diào)用mutation癣丧;還是直接action去做異步axious槽畔,根據(jù)不同的業(yè)務(wù)場(chǎng)景有不同的選擇,也有不同的好處體現(xiàn)出來胁编。
比如多次遇到的異步(如axious請(qǐng)求接口改變state)那就直接放在action里面厢钧,需要的時(shí)候頁面組件直接使用this.$store.dispatch就可以不用重復(fù)寫axious,所以vuex只是為了更靈活使開發(fā)者多一個(gè)選擇嬉橙,讓代碼盡可能的變動(dòng)優(yōu)雅早直。
Actions中的方法有兩個(gè)默認(rèn)參數(shù)
context 上下文(相當(dāng)于箭頭函數(shù)中的this)對(duì)象
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)項(xiàng)目龐大,狀態(tài)非常多時(shí)拾给,可以采用模塊化管理模式祥得。Vuex 允許我們將 store 分割成模塊(module)。每個(gè)模塊擁有自己的 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某個(gè)方法和以前一樣,會(huì)自動(dòng)執(zhí)行所有模塊內(nèi)的對(duì)應(yīng)type的方法:
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')