框架中的状态管理
第一篇 vuex(请先看神图)
单项数据流
vuex管理流程
状态管理应用包含三部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
进入实战
- 在使用全局安装vue vue-cli
- 使用vue全家桶指令vue create 项目名称
- 安装vuex-- yarn add vuex
1.打开main.js文件,此为vue项目的入口在这个文件中,创建vue实例,并挂在其他模块插件,在new构造函数中挂载store,store为整个vuex仓库,还可以挂载router路由最后记住挂载根节点
import router from './router/'
import store from './store/'
new Vue({
store,
router,
render(h) {
return h(App)
}
}).$mount('#app')
2.创建与pages同级的文件夹store,创建index.js
- 导入相应的包,并在Vue上使用Vuex
- 创建Vuex实例 new Vuex.Store({})
- 关键部分来了:在实例中定义Vuex灵魂部分state、getters、mutation、action、module,在后面会阐述,先看看我的简单布局
import Vue from 'vue'
import Vuex from 'vuex'
import http from '../utils/http'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
data: {}
},
getters: {
},
mutations: {
setFirstData(state, result) {
state.data = result
},
},
actions: {
async loadFirstData({commit}, params) {
let result = await http.get(params.firstReq)
commit('setFirstData', result)
},
},
module: {
状态树
}
})
export default store
3.看完大致结构,能帮助初学者快速搭建,当然每个单独的模块也可以单独定义在外面,再引入实例中。接下来我们来分别讲一讲五大核心的各自作用。
state
Vuex使用的单一状态树,在一个状态树中用一个对象,包裹着你定义的所有状态。
当数据量大,且分为不同模块时,我们还可以使用module,后面会讲到。
getter(getters)
相信在学Vuex之前,大家已经了解Vue中的计算属性,用来监控data中的状态是否发生变化。其实getters类似于计算属性computed,我们可以在该对象中定义多个方法,当state中的数据发生变化,函数就会执行并返回新的状态。
getter的返回值会根据他的依赖被缓存起来,且只有当它的依赖值发生变化才会被重新计算。
注意:getter中定义函数,函数的一个参数为state,及上面定义的状态。
Getter 也可以接受其他 getter 作为第二个参数。
mutation(mutations)
在Vuex中,想要更改store中的状态只有一个方法,那就是mutation。在mutation中你可以定义多个方法,这些方法的操作,最终是改变你在state中定义的属性,且这些方法接收state作为第一参数,当你想传入参数给该方法时,第二参数:载荷payload,该payload可以是对象或其他基本类型
方法(state,payload) { }
注意:mutation中确实是定义了很多方法,但你只能通过store.commit('方法名')来调用。mutation必须必须是同步函数,不要在方法中进行异步操作
支持的三种调用方式
store.commit({
type: 'increment',
amount: 10
})
store.commit('increment', {
amount: 10
})
store.commit('increment', 10)
action(actions)(详细再看vuex官网)
看完到上面mutation时,发现mutation有一个尴尬的地方,它只能进行同步操作,但我们往往需要请求接口资源,进行异步操作。action就是来弥补mutation的不足的地方,但在使用action有几个注意的地方。
- 不要尝试在action中直接改变state中的状态。你也改不了。(#^.^#)
- action提交的是mutation,而不是直接修改状态。
- 通过context.commit(提交一个mutation方法)
摘抄点官方文档:
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
当然你也可以使用ES6的解构赋值 { xx } 将commit从context解构出来。
在所需组件中如何调用action方法:
store.dispatch('increment')
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
module(此处还有许多细节请查看官网)
顾名思义:模块,解决最开始谈到的问题,Vuex维护的是一颗单一状态树,但当这颗状态树过于庞大时,就显得不好维护和提取所需属性。这个时候单一的状态树可以在分为多个模块,就像树的分支,在每一个单独的分支上,依旧有state,mutation,getter,action,module ,每个模块还可以在嵌套多个子模块。
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 的状态
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:
const moduleA = {
// ...
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}}
如何在组件中使用
以上讲完store内部的定义和部分规则,那么到了实践者最关心的环节,如何在组件中使用vuex管理的状态和方法呢!
在Vuex中还有配对的4个方法,需要谁结构谁
mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})}
mapGetter
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}}
mapMutations
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}}
mapActions
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}}
《狮心女孩》喜剧片高清在线免费观看:https://www.jgz518.com/xingkong/26725.html
你的文章让我感受到了无尽的欢乐,谢谢分享。 http://www.55baobei.com/5wxuzng6gy.html
你的才华让人惊叹,请继续保持。 http://www.55baobei.com/0KywSE0cRC.html
《尼罗河的希尔顿事件》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/7076.html
想想你的文章写的特别好https://www.ea55.com/
不错不错,我喜欢看 https://www.jiwenlaw.com/
小橘子
憨批