day02 5.21
三、vuex
1、使用场景、好处
使用场景:需要构建一个中大型单页应用,您很可能会考虑如何更好的在组件外部管理状态,Vuex将会成为自然而然的选择。
优点:当你在state中定义了一个数据之后,可以在所在项目中的任何一个组件里进行获取、进行修改、并且你的修改可以得到全局的响应变更。
2、概念、定义
定义:Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式储存管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
3、几部分组成(五大核心)
- state:
数据 定义初始数据
- mutations:
唯一可以修改state数据的场所 (更改Vuex的store中的状态的唯一方法就是提交mutation)
- actions:
Actions 类似于 mutation,但是Actions 提交的是 mutation,而不是直接变更状态 (数 据)。
使用commit调用 mutations 里的方法
Actions 可以异步操作。 Action页面中通过 this.$store.dispatch(“xxxx”);方法触发
- getters:
可以对 state 进行计算操作,它就是 store 的计算属性虽然在组件内也可以做计算属性,
但是 getters可以在多给件之间复用如果一个状态只在一个组件内使用,是可以不用 getters。
类似于vue组件中的计算属性,对state数据进行计算(会被缓存)
- modules:
- 模块化管理store(仓库),每个模块拥有自己的 state、mutation、action、getter 分模块化的管理
面对复杂的应用程序,当管理的状态比较多时
详细跳转
4、高级用法----- 辅助函数(语法糖)
1. 有那几个辅助函数(4大金刚)
- mapState
- mapActions
- mapMutations
- mapGetters
注意:
…mapactions 和 …mapgetters都是vuex提供的语法糖,在底层已经封装好了,拿来就
能用,简化了很多操作。其中…mapActions([‘clickAFn’])
相当于this.$store.dispatch(‘clickAFn’,{参数}),mapActions中只需要指定方法名即可,参数省略。
...mapGetters(['resturantName'])相当于this.$store.getters.resturantName
2.使用
<script>
//这我们引入 action 和 getters
import {mapActions, mapGetters} from 'vuex'
export default {
name: 'A',
data () {
return {
}
},
//action 在 methods 中展开 ****************************
methods:{
...mapActions( // 语法糖
['modifyAName'] // 相当于this.$store.dispatch('modifyName'),提交这个方法
),
trunToB () {
this.$router.push({path: '/componentsB'}) // 路由跳转到B
}
},
//getters 在 computed 计算属性中展开 *********************
computed: {
...mapGetters(['resturantName']) // 动态计算属性,相当于this.$store.getters.resturantName
}
}
</script>
3.优点
辅助函数可以把vuex中的数据和方法映射到vue组件中。达到简化操作的目的
5、高级用法----- 数据持久化
问题:存储在vuex中的状态,刷新页面,会丢失。为了解决刷新页面数据丢失,才有了数据持久化
最简单的做法就是利用插件 vuex-persistedState。
1. 安装
cnpm install vuex-persistedState -S
备注:*
-S 是–save的简写,意为:把插件安装到dependencies(生产环境依赖)中
-D是–save-dev的简写,意为:把插件安装到devDependencies(开发环境依赖)中
2.使用
//在vuex 里面引入
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
state,
mutations,
actions,
getters,
//插件
plugins: [createPersistedState({
//本地存储
storage: sessionStorage,
key: "token"
})]//会自动保存创建的状态。刷新还在
})
参数:
storage:存储方式。(sessionStorage,localStarage)
key:定义本地存储中的key
6、高级语法---- 模块化管理数据 (modules)
什么时候需要用到模块管理vuex数据
模块化的概念已经在js、css中大量的用到,已不再陌生,其可增加代码的复用、扩展性、维护性等,对于一个大型的系统来说,必不可少。这里也希望提供一种有效的模块化数据管理方式,让协作变的更为高效。
当项目较大时,单一state,就会十分庞大,管理和阅读,十分困难,此时使用vuex的另一个核心知识点module模块化
模块化,顾名思义,就是将store分成不同的版块,按需分类,简单的定义方式
import Vue from "vue"
import Vuex from "vuex"
VUe.use(Vuex)//使用插件
export default new Vuex.store({
state:{},//全局的state
modules:{
moduleA:{ //A模块
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
}
}
})
这样就简单的定义了一个模块
但是这并没有达到,我们想要的阅读性良好的感觉,我们应该将模块单独导出,定义成一个独立文件 index文件
在里面创建模块A
//moduleA.js
const moduleA ={
moduleA:{ //A模块
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
}
export default moduleA
//index.js 也就是上面的创建的index文件
import Vue from "vue"
import Vuex from "vuex"
import moduleA from"./moduleA.js"
VUe.use(Vuex)//使用插件
export default new Vuex.store({
state:{},//根下的state
modules:{
moduleA: moduleA //store.state.mofuleA 访问到状态
}
}
})
这样才是我们预期的阅读性良好,在外部文件可以通过**this.$store.state.**来访问
模块局部状态(下面是文档中的例子)
//细致解析模块中的参数
//在局部中,接受的第一个参数为局部的state,在getters和actions中第三个参数,
rootState,暴露的就是定义在原本store下的
state,相当于全局的state,
const moduleA = {
state: { count: 0 },
mutations: {
increment (state) {
// 这里的 `state` 对象是模块的局部状态
state.count++
}
},
getters: {
doubleCount (state, getters, rootState) {
return state.count * 2
}
},
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
4.使用方式 (???)
//在需要的页面
import {createNamespacedHelpers, mapState} from ‘vuex’
//结构赋值
const{mapGetters,mapActions,mapMutations} = createNamespacedHelpers('moduleA')
const { mapActions: mapOtherActions, mapGetters: mapOtherGetters } = createNamespacedHelpers('moduleB')
export default{
data() {
return {
}
},
//这样就能将想要的方法,变量解构到,当前页面,之后和正常使用一样,使用变量
computed: {
...mapState({
count : state => state.moduleA.count
}),
...mapGetters(['doubleCount']),
...mapOtherGetters(['doubleCount'])
},
methods: {
...mapActions(['incrementIfOddOnRootSum']),
...mapMutations([' increment']),
},
created() {
const pid = this.$route.query.pid
this.loadDataAsync(keep, pid)
}
}