一、Vuex 概述
1. 官方文档:https://vuex.vuejs.org/zh/Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
2. Vuex简单理解: Vue 应用中的每个组件在 data() 中封装着自己数据属性,而这些 data 属性都是私有的,完全隔离的。 如果我们希望多个组件都能读取到同一状态数据属性,或者不同组件的行为需要更新同一状态数据属 性, 这就需要一个将共享的状态数据属性进行集中式的管理。 这就是 Vuex 状态管理所要解决的问题。
3.上面复制的,我写不出这么深刻的理解。
二、整整试试
1.先创建一个Vue项目,手动安装,vuex Router ,2.x版本然后一顿回车,哈哈哈
2.然后运行一下服务
3.面试爱问:每一个 Vuex 应用的核心就是 store(仓库)
4.在store文件下的index.js中添加?count:?0:
export default new Vuex.Store({
state: {
count: 0
},
mutations: {},
actions: {},
modules: {}
})
5.然后让他在页面中显示,找到views的home.vue:
<template>
<div class="home">
<h1>1111</h1>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
6.效果:
7.用{{$store.state}}来获取状态对象,
<template>
<div class="home">
<h1>{{$store.state.count}}</h1>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
8.效果:
?9.我们可以改变一下这个值count,通过mutations,回到store文件下的index.js中:
mutations: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
}
},
10.再回到views的home.vue:
<template>
<div class="home">
<h1>{{$store.state.count}}</h1>
<button @click="add">++</button>
<button @click="decrement">--</button>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
11.在export?default里添加方法:
export default {
name: "Home",
components: {
HelloWorld,
},
methods: {
add() {
},
decrement() {},
},
};
12.官网--可以从组件的方法提交一个变更-----this.$store.commit:
methods: {
add() {
this.$store.commit("increment");
},
decrement() {
this.$store.commit("decrement");
},
},
13.现在可以实现点击++时,0++,点击--时,0--
14.就像官网所说,store当成一个仓库,然后通过在组件中去调用它的内部的方法,来实现对它的改动。
三、试试奥----mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,不能直接调用一个 mutation,需要以相应的 type 调用?store.commit?方法
1.那么,我们可不可以在其他组件中使用它呢,在views的about.vue中,
<template>
<div class="about">
<h1>{{ $store.state.count }}</h1>
</div>
</template>
2.结果发现也能拿到。
3.那么,我们可不可以在添加一个新值呢,加一个n,回到store文件下的index.js中:
mutations: {
increment(state, n) {
state.count += n
},
decrement(state) {
state.count--
}
},
在回到views的home.vue:
methods: {
add() {
this.$store.commit("increment",10);
},
decrement() {
this.$store.commit("decrement");
},
},
4.结果发现也能拿到。这叫载荷,可以向?store.commit ?传入额外的参数,即 mutation 的?载荷(payload)
四、Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
1.在store文件下的index.js中:
actions: {
dec({ commit }) {
commit("decrement")
},
},
2.在组件中使用?this.$store.dispatch('xxx') ?分发 action,在回到views的home.vue:
decrement() {
// this.$store.commit("decrement");
this.$store.dispatch('dec')
},
3.测试可以实现减操作。
4.在Action中,结构赋值形式添加一个新值,在store文件下的index.js中:
add({ commit }) {
commit("increment", 10)
}
在回到views的home.vue:
add() {
// this.$store.commit("increment",10);
this.$store.dispatch('add')
},
5.测试可以实现加10操作。
6.默认形式添加一个新值,在store文件下的index.js中,把原来的add()注释上,添加:
add(contxt) {
contxt.commit("increment", 10)
}
7.测试发现也可以实现加10操作。
五、?派生属性 getter
1. 理解 :
有时候我们需要从 store 中的 state 中派生出一些状态。例如:基于上面代码,增加一个 desc 属性,当 count 值小于 50,则 desc 值为 吃饭 ; 大于等于 50 小于100,则desc 值为 睡觉 ; 大于100 , 则 desc 值为 打豆豆 。这时我们就需要用到 getter 为我们解决。getter 其实就类似于计算属性(get)的对象.组件中读取 $store.getters.xxx?
2.实操
修改 store\index.js ,增加 getters 选项注意:getters 中接受 state 作为其第一个参数,也可以接受其他 getter 作为第二个参数
getters: {
desc(state) {
if (state.count < 50) {
return "吃饭"
} else if (state.count < 100) {
return "睡觉"
} else {
return "打豆豆"
}
}
}
修改 views\Home.vue, 显示派生属性的值:
<template>
<div class="home">
<h1>{{ $store.state.count }}</h1>
<h2>{{$store.getters.desc}}</h2>
<button @click="add">++</button>
<button @click="decrement">--</button>
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
3.效果:
?
六、Module模块化项目结构
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter 等,参见以下代码模型?
const moduleA = { ?
state: { ... }, ? mutations: { ... }, ? actions: { ... }, ? getters: { ... }
?} ?
const moduleB = { ?
state: { ... }, ? mutations: { ... }, ? actions: { ... }
?} ?
const store = new Vuex.Store({ ? modules: { ? a: moduleA, ? b: moduleB ?} ?})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
1.举个例子,修改 store\index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let A = {
state: {
count: 0
}, //存值
// 下面都是方法
mutations: {
increment(state, n) {
state.count += n
},
decrement(state, n) {
state.count -= n
}
},
actions: {
dec({ commit }) {
commit("decrement", 10)
},
// add({ commit }) {
// commit("increment", 10)
// },
add(contxt) {
contxt.commit("increment", 10)
}
},
getters: {
desc(state) {
if (state.count < 50) {
return "吃饭"
} else if (state.count < 100) {
return "睡觉"
} else {
return "打豆豆"
}
}
}
}
export default new Vuex.Store({
modules: {
a: A
},
})
2.修改views\Home.vue:
<template>
<div class="home">
<h1>{{ $store.state.count }}</h1>
<h2>{{$store.getters.desc}}</h2>
<h3>{{$store.state.a.count}}</h3>
<button @click="add">++</button>
<button @click="decrement">--</button>
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
3.效果:
?4.为了保证变量重复的情况下也能使用,我们在index.js中引入,使它变成局部作用:
namespaced: true,
5.在home.vue中:
methods: {
add() {
// this.$store.commit("increment",10);
this.$store.dispatch('a/add')
},
decrement() {
// this.$store.commit("decrement");
this.$store.dispatch('a/dec')
},
},
6.效果:
7.在创建一个变量B:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let A = {
namespaced: true,
state: {
count: 0
}, //存值
// 下面都是方法
mutations: {
increment(state, n) {
state.count += n
},
decrement(state, n) {
state.count -= n
}
},
actions: {
dec({ commit }) {
commit("decrement", 10)
},
// add({ commit }) {
// commit("increment", 10)
// },
add(contxt) {
contxt.commit("increment", 10)
}
},
getters: {
desc(state) {
if (state.count < 50) {
return "吃饭"
} else if (state.count < 100) {
return "睡觉"
} else {
return "打豆豆"
}
}
}
}
let B = {
namespaced: true,
state: {
count: 0
}, //存值
// 下面都是方法
mutations: {
increment(state, n) {
state.count += n
},
decrement(state, n) {
state.count -= n
}
},
actions: {
dec({ commit }) {
commit("decrement", 10)
},
// add({ commit }) {
// commit("increment", 10)
// },
add(contxt) {
contxt.commit("increment", 10)
}
},
getters: {
desc(state) {
if (state.count < 50) {
return "吃饭"
} else if (state.count < 100) {
return "睡觉"
} else {
return "打豆豆"
}
}
}
}
export default new Vuex.Store({
modules: {
a: A,
b: B
},
})
?在home.vue:
<template>
<div class="home">
<h1>{{ $store.state.count }}</h1>
<h2>{{$store.getters.desc}}</h2>
<h3>{{$store.state.a.count}}</h3>
<h3>{{$store.state.b.count}}</h3>
<button @click="add">++</button>
<button @click="decrement">--</button>
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
修改方法:
methods: {
add() {
// this.$store.commit("increment",10);
this.$store.dispatch("a/add");
this.$store.dispatch("b/add");
},
decrement() {
// this.$store.commit("decrement");
this.$store.dispatch("a/dec");
this.$store.dispatch("b/dec");
},
},
8.效果:
?七、标准项目结构
如果所有的状态都写在一个 js 中,这个 js 必定会很臃肿,Vuex 并不限制你的代码结构。但是它建议你按以下代码结构来构建项目结构:
1.?重构项目结构
1. 1在src下新建一个newStore文件夹,?在此文件夹下创建?index.js,actions.js,mutations.js和modules 目录,在该目录下创建?demo1.js?和demo2.js?
demo1.js:
let A = {
namespaced: true,
state: {
count: 0
}, //存值
// 下面都是方法
mutations: {
increment(state, n) {
state.count += n
},
decrement(state, n) {
state.count -= n
}
},
actions: AA,
getters: {
desc(state) {
if (state.count < 50) {
return "吃饭"
} else if (state.count < 100) {
return "睡觉"
} else {
return "打豆豆"
}
}
}
}
export default A
demo2.js :
let B = {
namespaced: true,
state: {
count: 0
}, //存值
// 下面都是方法
mutations: {
increment(state, n) {
state.count += n
},
decrement(state, n) {
state.count -= n
}
},
actions: {
dec({ commit }) {
commit("decrement", 10)
},
// add({ commit }) {
// commit("increment", 10)
// },
add(contxt) {
contxt.commit("increment", 10)
}
},
getters: {
desc(state) {
if (state.count < 50) {
return "吃饭"
} else if (state.count < 100) {
return "睡觉"
} else {
return "打豆豆"
}
}
}
}
export default B
?newStore\index.js:
import Vue from 'vue'
import Vuex from 'vuex'
import A from './modules/demo1.js'
import B from './modules/demo2.js'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
a: A,
b: B
},
})
在main.js中把原来的注释上,导入新的store,也就是newStore:
import store from './newStore'
在actions.js中:
let AA = {
dec({ commit }) {
commit("decrement", 10)
},
add(contxt) {
contxt.commit("increment", 10)
}
}
export { AA }
2. 正常访问, 与重构前一样
|