1惭载、VueX的介紹與作用解析
VueX:是一個專門為vue.js應用程序開發(fā)的狀態(tài)管理模式
1)旱函、它采用集中式存儲管理應用的所有組件的狀態(tài),并以相應的規(guī)則保證狀態(tài)以一種可預測的方式發(fā)生變化描滔。
2)棒妨、VueX也集成了Vue的官方調(diào)試工具 devtools extension,提供了諸如零配置的time-travel 調(diào)試含长、狀態(tài)快照導入導出等高級調(diào)試功能券腔。
狀態(tài)管理是什么?
狀態(tài)管理模式拘泞、集中式存儲管理這些名字有點高大上纷纫,讓人找摸不透。其實你可以簡單的將其看成把需要多個組件共享的變量全部存儲到一個對象里面陪腌;然后涛酗,將這個對象放在頂層的Vue實例中,讓其他組件可以使用偷厦;
應用場景:
用戶的登錄狀態(tài)商叹、用戶名稱、用戶頭像等
1.1只泼、vux 單界面到多界面狀態(tài)管理切換
安裝Vuex命令:
npm install vuex --save
示例代碼如下:
1)剖笙、配置vuex,一般會新建一個文件夾请唱,獨立管理vuex配置:新建文件夾 store/index.js
import Vue from 'vue';
import Vuex from 'vuex'
//安裝插件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state :{
num:0
},
mutations:{
//方法
addition(state){
state.num++;
},
subtract(state){
state.num--;
}
},
actions:{},
getters:{},
modules:{}
});
//導出
export default store;
2)弥咪、在main.js中進行掛載
import store from "./store";
new Vue({
el: '#app',
store,
render: h => h(App)
})
3)、新建組件 Index.vue
<template>
<div>
<span> {{ this.$store.state.num }}</span><br>
<button @click="Add">+</button>
<button @click="Subtract">-</button>
</div>
</template>
<script>
export default {
name: "Index",
methods:{
Add(){
this.$store.state.num++;
},
Subtract(){
this.$store.state.num--;
}
}
}
</script>
<style scoped>
</style>
4)十绑、新建組件 Info.vue 聚至,代碼如下:
<template>
<div>
<span>{{ this.$store.state.num }}</span><br>
</div>
</template>
<script>
export default {
name: "Info"
}
</script>
<style scoped>
</style>
5)、在App.vue 中掛載兩個組件本橙,代碼如下:
<template>
<div id="app">
<Index/>
<Info/>
</div>
</template>
<script>
import Index from './components/Index'
import Info from "./components/Info";
export default {
name: 'App',
components: {
Index,
Info
}
}
</script>
<style>
</style>
總結:
vuex 的安裝扳躬、配置以及使用狀態(tài)。
如果修改狀態(tài)值甚亭,以上的代碼是可以使用的贷币,但是官方是不建議這樣使用,因為這樣使用是無法監(jiān)聽是誰修改的這個狀態(tài)亏狰。
修改狀態(tài)值是在 mutations 進行修改狀態(tài)的值役纹,這樣就可以監(jiān)聽是誰修改的值,具體使用方法看實例代碼暇唾。
1.2促脉、Vuex-state 單一狀態(tài)樹的理解:
state:狀態(tài)值 單一狀態(tài)樹
單一狀態(tài)樹:單一數(shù)據(jù)源
mutations:修改狀態(tài)值
action:進行一些異步操作
getters:類似于組件中的計算屬性
getters的使用實例:
import Vue from 'vue';
import Vuex from 'vuex'
//安裝插件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state :{
num:0
},
mutations:{
//方法
addition(state){
state.num++;
},
subtract(state){
state.num--;
}
},
actions:{},
//getters的使用
getters:{
multiply(state){
return state.num*2;
}
},
modules:{}
});
//導出
export default store;
vue調(diào)用方法:
{{this.$store.getters.multiply}}
modules :劃分模塊辰斋,根據(jù)不同的模塊進行一系列的操作
mutations的使用
更新狀態(tài)唯一的方式就是 提交 mutations 。
mutations 主要包括兩部分:
①瘸味、字符串類型事件
②宫仗、一個回調(diào)函數(shù),該毀掉函數(shù)的第一個參數(shù)是state
1)硫戈、示例代碼: store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//安裝組件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state: {
num: 0
},
mutations: {
Add(state) {
state.num++;
},
Cut(state) {
state.num--;
},
AddFive(state,payload){
console.log(payload)
//第一種接收
state.num = state.num + payload;
//第二種接收 第二個參數(shù)是一個對象
state.num = state.num + payload.num1;
}
}
});
//導出
export default store;
2)锰什、組件中調(diào)用,示例代碼:
//不傳參
this.$store.commit('mutations方法名稱');
//第一種傳參
this.$store.commit('mutations方法名稱',參數(shù));
/第二種傳參
this.$store.commit({type:'mutations方法名稱',參數(shù) });
總結: mutations中函數(shù)傳參下硕,第一個參數(shù)state是固定的 丁逝,第二個參數(shù)是要傳遞的。
getters的使用:
getters的使用和組件中的計算屬性差不多梭姓,示例代碼如下:
import Vue from 'vue';
import Vuex from 'vuex';
//安裝組件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state: {
num: 0
},
getters:{
//不傳參
numAddNum(state){
return state.num+state.num;
},
//傳遞 參數(shù)
numAddNumParms(state,getters){
return s =>{
return getters.numAddNum + s;
}
}
}
});
//導出
export default store;
在組件中調(diào)用霜幼,示例代碼如下:
<!--不傳參-->
<div>這是getters計算的值:{{this.$store.getters.numAddNum}}</div>
<!--傳遞參數(shù)-->
<div>這是getters傳參計算的值:{{this.$store.getters.numAddNumParms(2)}}</div>
Mutation 的響應規(guī)則
響應規(guī)則:
①、提前store中初始化屬性誉尖。
②罪既、當給state 中的對象添加新屬性時,使用下面的方式:
方式1:使用Vue.set(obj,'newProp',123)
方式2:用新對象給舊對象重新賦值
示例代碼如下: store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//安裝組件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state: {
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
AddProperty(state) {
console.log("添加對象屬性");
Vue.set(state.student[0], 'adress', '12312');
}
}
});
//導出
export default store;
組件中調(diào)用铡恕,示例代碼如下:
<div>這是student對象值:{{this.$store.state.student}}</div>
<button @click="AddProperty">添加student對象屬性</button>
<script>
export default {
name:'Index',
methods:{
AddProperty(){
this.$store.commit('AddProperty');
}
}
}
</script>
mutation的類型常量
由于項目越來越大琢感,mutation中的方法越來越多,為了更好的管理這些方法探熔,可以將這些方法名單獨抽出文件來進行管理驹针。
①、 示例代碼如下:新建 mutation-types/index.js
export const ADDPROPERTY = 'AddProperty'
②诀艰、在store/index.js文件中導入文件柬甥,示例代碼:
import Vue from 'vue';
import Vuex from 'vuex';
import * as types from '../mutation_types'
//安裝組件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state: {
num: 0,
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
[types.ADDPROPERTY](state) {
console.log("添加對象屬性");
Vue.set(state.student[0], 'adress', '12312');
}
}
});
//導出
export default store;
③、在組件中調(diào)用其垄,示例代碼如下:
<div>這是student對象值:{{this.$store.state.student}}</div>
<button @click="AddProperty">添加student對象屬性</button>
<script>
import * as types from '../mutation_types'
export default {
name:'Index',
methods:{
AddProperty(){
this.$store.commit(types.ADDPROPERTY);
}
}
}
</script>
Vuex-Action 的基本使用
Action主要應用于異步苛蒲,同步方法在Mutation中進行定義。
基本使用:在store/index.js 示例代碼:
import Vue from 'vue';
import Vuex from 'vuex';
import * as types from '../mutation_types'
//安裝組件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state: {
num: 0,
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
[types.ADDPROPERTY](state) {
console.log("添加對象屬性");
Vue.set(state.student[0], 'adress', '12312');
}
},
actions:{//用于一步操作
aUpdata(context){
setTimeout(() => {
console.log('執(zhí)行異步操作');
//異步操作在Actions中進行绿满,但是修改值必須經(jīng)過mutation
context.commit(types.ADDPROPERTY);
}, 2000);
}
}
});
//導出
export default store;
在組建中調(diào)用臂外,示例代碼:
<div>這是student對象值:{{this.$store.state.student}}</div>
<button @click="AddPropertyAsync">異步操作添加student對象屬性</button>
<script>
import * as types from '../mutation_types'
export default {
name:'Index',
methods:{
AddPropertyAsync(){
this.$store.dispatch('aUpdata');
}
}
}
</script>
總結:
異步操作必須在Actions中進行操作,但是修改的值必須經(jīng)過Mutation喇颁。
Actions 與 Promise 結合使用寄月,示例代碼:
import Vue from 'vue';
import Vuex from 'vuex';
import * as types from '../mutation_types'
//安裝組件
Vue.use(Vuex);
//創(chuàng)建對象
const store = new Vuex.Store({
state: {
num: 0,
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
[types.ADDPROPERTY](state) {
console.log("添加對象屬性");
Vue.set(state.student[0], 'adress', '12312');
}
},
actions:{
aUpdata(context){
return new Promise((resolve, reject) => {
console.log('執(zhí)行異步操作');
context.commit(types.ADDPROPERTY);
resolve('Ok');
});
}
}
});
//導出
export default store;
組件中調(diào)用,示例代碼如下:
<div>這是student對象值:{{this.$store.state.student}}</div>
<button @click="AddPropertyAsync">異步操作添加student對象屬性</button>
<script>
import * as types from '../mutation_types'
export default {
name:'Index',
methods:{
AddProperty(){
this.$store.commit(types.ADDPROPERTY);
},
AddPropertyAsync(){
this.$store.dispatch('aUpdata').then((res)=>{
console.log('執(zhí)行成功');
console.log(res);
});
}
}
}
</script>
modules的基本使用:
Vue使用單一狀態(tài)樹,那么也意味著有很多狀態(tài)都得需要交給Vuex來管理无牵,當應用變的很復雜時漾肮,那么store對象會變得很臃腫,為了解決這個問題茎毁,vuex允許我們將store分割成很多模塊克懊,每個模塊都有自己的 state actions getters mutations忱辅。
示例代碼如下: store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//安裝
Vue.use(Vuex);
const TestModule = {
state: {
num: 0,
payload:0,
name:'小剛'
},
mutations: {
add(state) {
state.num++;
},
subtraction(state) {
state.num--;
},
parms(state,payload){
state.payload = payload;
}
},
getters:{
fullname(state){
return state.name = '李'+state.name;
},
fullname1(state,getters){
return getters.fullname+2222;
},
fullname2(state,getters,rootState){
return getters.fullname1+rootState.rootname;
}
},
actions:{
updateNameAsync(context){
setTimeout(()=>{
context.commit('parms',"再見");
context.commit('updaterootName');
context.rootGetters.test ('開發(fā)');
console.log(context);
},1000);
}
}
};
//創(chuàng)建對象并導出對象
export default new Vuex.Store({
state:{
rootname:'fuck'
},
mutations:{
updaterootName(state)
{
state.rootname = "you";
}
},
modules: {
TestModule
},
getters:{
test(state,getters)
{
return (s)=>{
return state.rootname = s;
}
}
}
});
組件中調(diào)用谭溉,示例代碼如下:
<template>
<div class="hello">
<h2>TestModule 的 state狀態(tài)值:{{this.$store.state.TestModule.num}}</h2>
<h2>TestModule 的 mutations 參數(shù)傳值:{{this.$store.state.TestModule.payload}}</h2>
<h2>TestModule 的 getters無參值:{{this.$store.getters.fullname}}</h2>
<h2>TestModule 的 使用getters參數(shù)獲取fullname函數(shù)在拼接值:{{this.$store.getters.fullname1}}</h2>
<h2>TestModule 的 使用rootgetters參數(shù)獲取根getter中的函數(shù)在拼接值:{{this.$store.getters.fullname2}}</h2>
<div>
<button @click="add">+</button>
<button @click="subtraction">-</button>
<button @click="parms">Mutations 傳值</button>
<button @click="updateAsync">異步修改</button>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods:{
add(){
this.$store.commit('add');
},
subtraction(){
this.$store.commit('subtraction')
},
parms(){
console.log(this.$store.commit('parms',4));
},
updateAsync(){
this.$store.dispatch('updateNameAsync');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
總結:
getters中可以調(diào)用根中state對象 關鍵字:rootstate
actions中的context參數(shù)也可以調(diào)用根中的rootGetters墙懂、rootstate、mutations扮念,詳細看以上代碼损搬。