之前在項目用到過Vuex,但用的時候都是前輩寫好的結構,知其然而不知所以然,看了幾篇博客以及官網的內容打算小小的整理一下,首先來拋玉引磚,推薦幾個我覺得通俗易懂的博客:
未將狀態使用Modules進行表達的:https://blog.csdn.net/u011068996/article/details/80216154 使用Modules進行表達的:https://segmentfault.com/a/1190000009404727 當然官網也很重要,雖然沒有中文的但是可以翻譯成中文頁面(中英對照著看不然理解會有偏差):https://vuex.vuejs.org/
(以下實際例子以vue-cli為背景進行)
(1)什么都不說這個是真的重要:
(2)與全局變量的區別
vuex的state狀態可以理解為響應式的雙向改變;其次,其狀態必須通過提交mutations進行改變
注意:
.getters的第三個參數rootState,可進行跨模塊調用state; .state 是會根據組合時模塊的別名來添加層級的【歸于根state】,后面的 getters,mutations ,actions 都是合并在 store 下 .getters不可重名,重名報錯;mutations與actions可重名,且重名訪問時按照模塊引入順序依次觸發
安裝:npm install vuex --save
main.js中引入
1.安裝【同上】
2.main.js中引入【同上】
3.src下store目錄結構
各個文件內容:
4.組件訪問(map方式演示):
map方式知識點:
篇文章,內容比較多,建議收藏!
官方解釋:Vuex 是專為 vue.js 應用程序開發的狀態管理模式。
什么是狀態管理?
簡單地講:可以把多個組件都需要的變量全部存儲到一個對象里面,然后這個對象放在頂層的 vue 實例中,讓其他組件可以使用。這樣多個組件就可以共享這個對象中的所有屬性。
有些同學想著,這么簡單我們自己在vue頂層定義一個對象不就可以實現共享了?我們發現雖然數據可以獲取到,但是如果在某個組件內,數據改變了,那我們如何修改數據,讓此數據在其他組件內保持最新呢?
我們的vuex就是為了提供一個在多個組件間共享狀態的插件,而且能夠實現實時響應。
vuex 是管理組件之間通信的一個插件,所以使用之前必須安裝。
2.1、安裝
1》使用 script 方式引入
<script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
2》使用包管理
npm install vuex --save //yarn add vuex
注意:vuex 必須依賴 vue 使用
2.2、搭建 store 實例
創建一個 store 文件夾,新建 index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);//使用vuex
export default new Vuex.Store({
state:{},
mutations:{},
getters:{},
actions:{},
modules:{}
})
在 main.js 處,掛載 store
import store from './store'
new Vue({
router,
render: h=>h(App)
})
//相當于
// Vue.prototype.$store=store
2.3、使用狀態
// store 中定義狀態
state:{
statue: '在線'
}
//在組件內使用
<div>組件內數據:{{ $store.state.status }} </div>
//在 js 中使用
mounted(){
console.log( this.$store.state.status )
}
3.1、state
state 存放 vuex 的基本數據,用來存儲變量的。
單一狀態樹
Vuex 使用單一狀態樹,即用一個對象就包含了全部的狀態數據。state 作為構造器選項,定義了所有我們需要的基本狀態參數。
在組件中引用 state 數據方式:
1》通過 vue 的 computed 獲取 vuex 的 state
export default new Vuex.Store({
state:{
online:true
}
})
computed:{
status(){
return this.$store.state.online
}
}
store 中的數據發生改變時,都會重新求取計算屬性,并更新相關 DOM。
2》如果需要使用多個參數時,都使用 computed 計算屬性,就會使代碼變的有些冗余和復雜,此時我們就可以借助 mapState 輔助函數。
//state 中數據比較多,引用到一個組件內
export default new Vuex.Store({
state:{
online:true,
per:[
{name:'qq',age:18}
],
role:'管理員'
}
})
//組件內
import { mapState } from 'vuex'
export default {
name: 'App',
computed: mapState({
online: state=> state.online,
per: 'per', // 'per'就相當于 state.per
role: 'role' // 'role'就相當于 state.role
})
}
vuex 使用單一狀態樹來管理應用層級的全部狀態,單一狀態樹能夠讓我們最直接的方式找到某個狀態的片段,而且之后的維護和調試過程,也可以非常方便管理和維護。
3.2、getters
從 store 中獲取一些 state 變異后的狀態。
使用的時候一般有兩種方式:
1》返回的結果只依賴于 state 中的數據
export default new Vuex.Store({
state:{
count:2,
},
getters:{
//返回 count 的 2 倍數據
countDouble(state){
return state.count*2
}
}
})
//組件中引用
<div> 獲取countDouble:{{ $store.getters.countDouble }} </div>
//運行結果
獲取countDouble:4
此處,$store.getters.countDouble 的使用與上邊的 $store.state.count 是一樣的。
2》getters 中返回的變異結果,依賴于某個 getters 中屬性返回結果
export default new Vuex.Store({
state:{
count:2,
},
getters:{
//返回 count 的 2 倍數據
countDouble( state ){
return state.count * 2
}
//返回 countDouble 的 2 倍數據
countDoubleT( state , getters ){
return getters.countDouble * 2
}
}
})
//組件中引用
<div> 獲取countDouble:{{ $store.getters.countDoubleT }} </div>
//運行結果
獲取countDouble:8
3.3、mutations
vuex 的store 狀態的更新唯一方式:提交 Mutation。
Mutations 主要包括兩部分:
1》、mutation 中的方法通過 commit 調用,不傳參數使用:
export default new Vuex.Store({
state:{
count:2,
},
mutations:{
incrs(state){
// count 加 1
state.count++
}
}
})
//組件調用
<button @click=" $store.commit('incrs') " >+</button>
{{$store.state.count}}
按鈕每點一次,count 就會自加一次。
2》mutations 傳遞參數
我們點擊加按鈕時,指定每次點擊增加的數值,如下:
export default new Vuex.Store({
state:{
count:2,
},
mutations:{
addNum( state,n ){
// count 加 1
state.count +=n
}
}
})
//組件調用
<button @click=" $store.addNum( 'incrs' , 5 ) " >+</button>
{{$store.state.count}}
//運行結果
每點一次按鈕,count 增加 5
上個實例傳遞的是一個參數,如果我們需要傳遞多個參數時,該如何實現呢?
3》mutations 傳遞多個參數
export default new Vuex.Store({
state:{
count:2,
},
mutations:{
addNum(state,payload){
// payload 是傳遞過來的參數對象
state.count +=payload.count
}
}
})
//組件調用
<button @click="addTen" >加10</button>
{{$store.state.count}}
export default{
methods:{
addTen(){
this.$store.commit({
type:'addNum',
count:10,
...//可以傳任意多個參數
})
}
}
}
//運行結果
每點一次按鈕,count 增加 10
上述方法是 mutations 特殊的提交封裝。包含了 type 屬性的對象,將整個 commit 的對象作為 payload 使用。
3.4、actions
mutations 提交更新數據的方法,必須是同步的,如果是異步使用就會出現問題,然后在項目開發中往往就會用到異步更新,比如網路請求數據。
actions 是類似于 mutation,功能大致相同,但是 actions 是用來替代 mutations 進行異步操作的。
1》actions 的基本使用
actions:{
aUpdateCount(context){
setTimeout(()=>{ //使用定時器模擬異步操作
context.commit('updateCount')
},2000)
}
},
mutations:{
updateCount(state){
state.count=5201314
},
}
// 組件內使用
{{$store.state.count}}
<button @click="$store.dispatch('aUpdateCount')">異步更新count</button>
//運行結果
點擊按鈕,兩秒后更新 count 值為5201314
值得注意的是,使用 actions 異步更新數據的時候,還是需要經過 mutations 中的方法,state 中的數據只能由 mutations 中的方法修改。
調用 mutations 中的方法,使用 commit 調用。
調用 actions 中的方法,使用 dispatch 調用。
2》異步更新的時候,也可以帶參數
// 功能:點擊按鈕,指定 count 修改的值
actions:{
aUpdateCount( context, payload ){
setTimeout(()=>{ //使用定時器模擬異步操作
context.commit( 'updateCount' , payload )
},2000)
}
},
mutations:{
updateCount( state , payload ){
state.count=payload
},
}
// 組件內使用
{{$store.state.count}}
<button @click="$store.dispatch( 'aUpdateCount', '我愛前端' )">異步更新count</button>
//運行結果
點擊按鈕,兩秒后更新 count 值為: 我愛前端
3》傳入異步參數
actions:{
//傳入promise
updateData(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('我學會了')
},2000)
})
},
}
//組件內調用
<button @click="ok">promise執行成功,返回"我學會了"</button>
methods:{
ok(){
this.$store.dispatch('updateData').then((res)=>{
console.log(res)
})
},
}
//運行結果
點擊按鈕,兩秒后打印:我學會了
3.5、modules
modules 是模塊的意思,vue 使用單一狀態樹,項目越來越大,store 中的數據越來越多,不便于數據的管理和維護,代碼也會變得臃腫。因此使用 modules ,把數據劃分到對應的某個模塊,既便于開發,也提高代碼的可讀性。
1》modules 簡單使用
import Vue from 'vue'
import Vuex from 'vuex'
import { Increase } from './mutation_type.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
actions: {},
getters: { },
mutations: { },
modules:{
a:{
state:{},
getters:{},
mutations:{},
actions:{}
},
b:{
state:{},
getters:{},
mutations:{},
actions:{}
}
},
})
//也可以整理為
const moduleA={
state:{},
getters:{},
mutations:{},
actions:{}
}
const moduleB={
state:{},
getters:{},
mutations:{},
actions:{}
}
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
actions: {},
getters: { },
mutations: { },
modules:{
a: moduleA,
b: moduleB
},
})
2》模塊中的數據如何使用呢?
const moduleA={
state:{
aName:'我是模塊a的數據'
},
getters:{},
mutations:{},
actions:{}
}
// 組件內引用
{{ $store.state.a.aName }}
3》調用模塊內的 mutations 中的方法,如何調用呢?
$store.commit('aChangeName')
調取模塊內的 mutations 中的方法,與之前是一模一樣的,程序會先從第一層 store 中查找方法,找不到方法時會繼續去模塊中查找。
4》調用模塊內的 getters 內方法
$store.getters.getName
需要注意的是,getters 中方法都是對 state 中數據變異,如果模塊的 getters 方法需要根 store 中的 state 呢?
getName(state,getters , rootState){
// state 表示當前模塊的 state
// getters表示當前模塊的getters
//rootState 表示根 store 內的state
}
5》模塊內的 actions 中的方法,使用 commit 調用 mutations 中方法時,只能調用本模塊內的 mutations 方法,不能調用外層的。
Vuex 的 store 中的 state 是響應式的,當 state 中數據發生改變時,vue 組件會自動更新。這就要求我們必須遵守一些vuex對應的規則:
提前在 store 中初始化好所需的屬性。
說人話,就是必須在state中定義的屬性才能做到響應式,如果是后加或刪除的,無法做到響應式。
舉個栗子:
mutations:{
changeName(state){
state.info.name='愛學習的前端人'
},
addAdrs(state){
state.info['address']="陜西西安"
},
}
{{this.$store.state.info}}
<button @click="$store.commit('changeName')">修改姓名</button>
<button @click="$store.commit('addAdrs')">增加地址</button>
此時點擊修改姓名的時候,可以做到響應式,而點擊“增加地址”按鈕時,頁面沒有任何反應,但是在開發者模式中可以看到數據有變化。
我們要響應式,該如何實現呢?
addAdrs(state){
state.info['address']="陜西西安"
//修改為:
Vue.set(state.info,'address','陜西西安')
},
同樣的如果要刪除 age 屬性時,使用 delete 也做不到響應式,需要修改為 Vue.delete。
實例:響應式刪除 age 屬性
deleteAge(state){
//delete state.info.age
//修改為
Vue.delete(state.info,'age')
},
//組件內容
{{this.$store.state.info}}
<button @click="$store.commit('deleteAge')">刪除年齡</button>
在 mutation 中定義很多事件類型,也就是方法名。當項目越來越大時,Vuex 管理的狀態越來越多,需要更新狀態的情況越來越多,那么意為著 Mutations 中的方法名越來越多,方法過多時,使用的時候需要花費大量精力去記住或來回切換文件找方法名,這樣很容易出錯,所以推薦大家使用一個常量,即使方法名出錯了,也會將錯就錯,程序并不會發生異常。
如:
// 新建 mutation_type.js 文件
//導出一個常量
export const Increase='increase'
// store.js文件
import Vue from 'vue'
import Vuex from 'vuex'
import { Increase } from './mutation_type.js'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
count:2,
},
mutations:{
[Increase](state){
state.count++
},
}
})
//組件內容
{{ $store.state.count }}
<button @click="add">加10</button>
import { Increase } from './store/mutation_type'
sxport default{
methods:{
add(){
this.$store.commit(Increase)
}
}
}
使用的時候,只需要記住 Increase 或者在 mutation_type.js 文件內查找就好了。
好了小編今天的文章就到此結束了,喜歡我的可以點個關注哦!
源:https://www.cnblogs.com/maoqian/p/15428820.html
概念:Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。
簡單點來說(說人話),就是實現任意組件中通信,并可以檢測數據的變化。
Vuex是集中于MVC模式中的Model層,規定所有的數據操作必須通過 action - mutation - state 的流程來進行,再結合Vue的數據視圖v-moder等雙向綁定特性來實現頁面的展示更新。
下面看一張圖來了解全過程。
簡述主要方法詳情:
總的一句話簡述就是:
Vue組件接收交互行為,調用dispatch方法觸發action相關處理,若頁面狀態需要改變,則調用commit方法提交mutation修改state,通過getters獲取到state新值,響應數據或狀態給Vue 組件,界面隨之更新。
npm install vuex --save
隨便叫啥,隨便建不建立文件夾。為了規范。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//準備actions---用于響應組件中的動作
const actions={
}
//準備mutations---用于操作數據(state)
const mutations={
}
//準備state---相當于data,用于存儲數據
const state={
}
//實例化創建并導出store
export default new Vuex.Store({
namespaced: true,//解決模塊命名沖突
actions,
mutations,
state,
})
注意:
我們在這一步創建index.js文件的時候導入并引用Vuex,因為我們要實例化Vuex對象。如果在main引入,會導致在main.js導入store的時候報錯。
import store from './store/index' //引入寫好的store
.....
new Vue({
el: '#app',
router,
store,//使用store
template: '',
components: { App }
})
先來一點簡單的存放數據,取出查看。在一系列操作之后我們的VM(View Model)和VC(View component)身上都已經都有store這個數據源對象。所以我們可以從store身上使用this.$store.state.xxx獲取數據。
在index.js中準備數據
const state={
name:'浪漫主義碼農',
age:18,
}
在組件中獲取數據
<template>
<div>
我放在store中的數據是 {{this.$store.state.name}}, {{this.$store.state.age}}
</div>
</template>
在知道每一個vm和vc身上都有store就可以好好操作了。
根據上面的原理圖,我們能知道vuex中規定只能通過提交mutation的方式去更改store中的狀態,包括action中的操作,也是通過提交mutation去修改。另外一點就是vuex中規定mutation中不能包含異步操作
我們來修改上面的name、age屬性。
const mutations={
modify_age(state) {//不帶參數修改age屬性,state是默認的參數
state.name="張三";
state.age=20;
},
modify_age2(state,payload) {//帶參數修改,payload是傳入的對象,官網叫載荷(payload)
state.name=payload.name;
state.age=payload.age;
}
}
在組件中,我們要使用this.$store.commit('xxx(方法名)', 參數;
參數可以是對象也可以是單一屬性
<template>
<div>
我放在store中的數據是 {{ this.$store.state.name }},
{{ this.$store.state.age }}
<button @click="setDefault">不帶參修改</button>
<button @click="setparameter">帶參修改</button>
</div>
</template>
<script>
export default {
methods: {
setDefault() {
this.$store.commit("modify_age");
},
setparameter() {
this.$store.commit("modify_age2",{name:"王五",age:100});//載荷形式,傳入可以使對象或者單個屬性
// this.$store.commit({//對象形式,傳入可以使對象或者單個屬性
// type: "modify_age2",
// name: "王五",
// age: 100,
// });
});
},
},
};
</script>
Action 類似于 mutation,不同在于:
后臺API請求在這個模塊進行請求。所有的操作最后都要到達mutation進行操作,更改state的狀態。
還是上面一個例子,異步修改state的屬性
先上代碼
const actions={
asy_modify (context) {//無參
setTimeout(()=> {//異步操作
context.commit("modify_age")
}, 2000);
},
asy_modify2 (context,plyload) {//有參
setTimeout(()=> {
context.commit("modify_age2",plyload);
}, 2000);
}
}
const mutations={
modify_age(state) {//不帶參數修改age屬性,state是默認的參數
state.name="張三";
state.age=20;
},
modify_age2(state,payload) {//帶參數修改,payload是傳入的對象,官網叫載荷(payload)
state.name=payload.name;
state.age=payload.age;
}
}
const state={
name: '浪漫主義碼農',
age: 18,
}
在組件中使用this.$store.dispatch('xxx')
<template>
<div>
我放在store中的數據是 {{ this.$store.state.name }},
{{ this.$store.state.age }}
<button @click="setDefault">不帶參修改</button>
<button @click="setparameter">帶參修改</button>
</div>
</template>
<script>
export default {
methods: {
setDefault() {
this.$store.dispatch("asy_modify");
},
setparameter() {
this.$store.dispatch("asy_modify2",{name:"王五",age:100});//載荷形式,傳入可以使對象或者單個屬性
// this.$store.dispatch({//對象形式,傳入可以使對象或者單個屬性
// type: "asy_modify2",
// name: "王五",
// age: 100,
// });
},
},
};
</script>
注意觀察時間,2s后變化。
分析一波:
getter,我們可以理解為是對store中state的一些派生狀態,也可以理解為一種計算屬性,它類似于計算屬性一樣,返回值會根據它的依賴被緩存起來,且依賴對象發生改變的時候它才會被重新計算。
getter屬性相當于很多個組件需要對數據進行一樣的處理,可以理解為公共的計算屬性。
這樣就很清晰了
Getter 接受 state 作為其第一個參數,也可以使用箭頭函數。
const getters={
get_object: function (state) {//無參
if (state.age < 18) {
return state.name + '未成年'
}
return state.name + '已經成年了'
},
get_object2: function (state) {//有參數
return function(value){
return state.name + value;
}
}
}
組件中{this.$store.getters.xxx來獲取
<template>
<div>
我放在store中的數據是 {{ this.$store.state.name }},
{{ this.$store.state.age }}
<br>
<span>不帶參數的數據:{{ this.$store.getters.get_object }}</span>
<br>
<span>帶參數的數據(攜帶一個剛好18歲):{{
this.$store.getters.get_object2("剛好18歲")
}}</span>
</div>
</template>
Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊。這里就不過多介紹了,看官方文檔(Module | Vuex (vuejs.org))
vuex提供了幾個的輔助函數,有mapState、mapGetter、mapMutation、mapAction。都是一些復雜語句的簡寫形式。
引入函數
import {mapState,mapGetters,mapMutation,mapAction} from 'vuex'
如果state中的數據很多,那我們要重復寫很多這樣的this.$store.state.XXX代碼,我們就可以通過mapState來映射。
數組的寫法
export default {
computed:{
...mapState(['name','age'])//自動就添加到了計算屬性中,此時就可以直接像訪問計算屬性一樣訪問它
}
};
如果你想取名別名的話,就要寫成對象的形式
...mapState(
{
myname: 'name',
myage: "age",
}
mapGetters和mapState很相似,只不過是映射Getters。替代this.$store.getters.XXX
computed: {
...mapGetters(['get_object','get_object2']),//數組形式寫法
...mapGetters({get1:'get_object',get2:'get_object2'})//可以取別名,對象形式寫法
},
替代this.$store.commit('XXX')
methods: {
...mapMutations(['modify_age','modify_age2']),//數組形式寫法
...mapMutations({modify:'modify_age',modify2:'modify_age2'}),//可以取別名,對象形式寫法
},
替代this.$store.dispatch('XXX')
methods: {
...mapActions(['asy_modify','asy_modify2']),//數組形式寫法
...mapActions({act_modify:'asy_modify',act_modify2:'asy_modify2'})//對象形式寫法
},
以上這些輔助函數,涉及到傳參都需在使用的計算屬性的時候傳入。
更具體的請看官網文檔,歡迎各位大佬指點江山。
https://vuex.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%A8%A1%E5%BC%8F
看到最后點贊收藏吧!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。