快速上手Vuex 到 手写简易 Vuex
快速上手Vuex-->手写简易 Vuex
前言
今天本篇文章是关于 Vuex
,大家使用 Vue
不会陌生吧
今天我们先对 Vuex
进行了解,然后讲下基本的用法,然后我们自己实现一个简易的 Vuex
往期精彩:
1.简介
Vuex 状态管理插件
在Vue
最重要就是 数据驱动 和 组件化,每个 组件都有自己 data
,template
和 methods
, data
是数据,我们也叫做状态,通过methods
中方法改变 状态来更新视图,在单个组件中修改状态更新视图是很方便的,但是实际开发中是多个组件(还有多层组件嵌套)共享同一个状态时,这个时候传参就会很繁琐,我们这里就引进 Vuex
来进行状态管理,负责组件中的通信,方便维护代码
Vuex 主要解决的问题
- 多个视图依赖同一个状态
- 来自不同视图的行为需要变更同一个状态
使用 Vuex 的好处
- 能够在
vuex
中集中管理共享的数据,易于开发和后期维护 - 能够高效地实现组件之间的数据共享,提高开发效率
- 在
vuex
中的数据都是响应式的
2.Vuex 基础使用
首先在Vue中添加 Vuex 插件
通过 vue-cli
添加了 Vuex
后,在项目的 src
目录下会多出一个 store
目录,目录下会有个 index.js
当然也通过 npm
进行安装 Vuex
npm install vuex --save
<span class="copy-code-btn">复制代码</span>
在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理
在 package.json 文件 scripts 中可以设置环境,当我们处于开发环境时,可以开启严格模式
开启严格模式的方式也是很简单的一行代码就可以
strict:products.env.NODE_ENV !== 'production'
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
// 在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理
strict:products.env.NODE_ENV !== 'production',
// 状态
state: {
},
// 用来处理状态
mutations: {
},
// 用于异步处理
actions: {
},
// 用来挂载模块
modules: {
}
})
复制代码
要使用 store 就在把 store 挂载到 Vue 中
把 store 挂载到 Vue 之后 ,所有的组件就可以直接从 store 中获取全局数据了
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
// 挂载到vue 中
store,
render: (h) => h(App),
}).$mount('#app')
复制代码
1.state
在 state 中添加数据
我们需要共享的状态都放在写在 state 对象里面
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {},
actions: {},
modules: {},
})
复制代码
组件中获取 state 中的数据
获取到 state
有两种方式
1.直接使用 this.$store.state[属性]
,(this
可以省略)
<template>
<div id="app">
{{ this.$store.state.name }}
{{ this.$store.state.age }}
</div>
</template>
复制代码
2.使用 mapState
通过 mapState
把 store
映射到 组件的计算属性,就相当于组件内部有了 state
里的属性
知道这里为啥要用 ...
展开吗,到时候实现 mapState
时就知道了
<template>
<div id="app">
{{ name }}
{{ age }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
}
}
</script>
<style scoped>
</style>
复制代码
注意
当store 中的值 和 当前组件有相同的状态,我们可以在 mapState 方法里传递一个对象 而不是一个数组,在对象中给状态起别名
computed: {
// name2 和 age2 都是别名
...mapState({ name2: 'name', age2: 'age'}])
}
复制代码
2.Mutation
Store
中的状态不能直接对其进行操作,我们得使用 Mutation
来对 Store
中的状态进行修改,虽然看起来有些繁琐,但是方便集中监控数据的变化
state
的更新必须是 Mutation
来处理
我们现在 mutaions 里定义个方法
如果想要定义的方法能够修改 Store
中的状态,需要参数就是 state
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {
// 在这里定义 方法
/**
*
* @param {*} state 第一个参数是 Store 中的状态(必须传递)
* @param {*} newName 传入的参数 后面是多个
*/
changeName(state, newName) {
// 这里简单举个例子 修改个名字
state.name = newName
},
},
actions: {},
modules: {},
})
复制代码
在组件中使用 mutations 中的方法
同样有两种方法在组件触发 mutations
中的方法
1.this.$store.commit() 触发
在 methods
中定义一个方法,在这个方法里面进行触发 mutations
中的方法
<template>
<div id="app">
<button @click="handleClick">方式1 按钮使用 mutation 中方法</button>
{{ name }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
},
methods: {
handleClick() {
// 触发 mutations 中的 changeName
this.$store.commit('changeName', '小浪')
}
},
}
</script>
<style scoped>
</style>
复制代码
2.使用 mapMutations
<template>
<div id="app">
<button @click="changeName('小浪')">方式2 按钮使用 mutation 中方法</button>
{{ name }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState
import { mapState, mapMutations } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
},
methods: {
// 将 mutations 中的 changeName 方法映射到 methods 中,就能直接使用了 changeName 了
...mapMutations(['changeName'])
},
}
</script>
<style scoped>
</style>
复制代码
3.Action
Action
和Mutation
区别
Action
同样也是用来处理任务,不过它处理的是异步任务,异步任务必须要使用 Action
,通过 Action
触发 Mutation
间接改变状态,不能直接使用 Mutation
直接对异步任务进行修改
先在
Action
中定义一个异步方法来调用Mutation
中的方法
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {
// 在这里定义 方法
/**
*
* @param {*} state 第一个参数是 Store 中的状态(必须传递)
* @param {*} newName 传入的参数 后面是多个
*/
changeName(state, newName) {
// 这里简单举个例子 修改个名字
state.name = newName
},
},
actions: {
/**
*
* @param {*} context 上下文默认传递的参数
* @param {*} newName 自己传递的参数
*/
// 定义一个异步的方法 context是 store
changeNameAsync(context, newName) {
// 这里用 setTimeout 模拟异步
setTimeout(() => {
// 在这里调用 mutations 中的处理方法
context.commit('changeName', newName)
}, 2000)
},
},
modules: {},
})
复制代码
在组件中是 Action 中的异步方法也是有两种方式
1.this.$store.dispatch()
<template>
<div id="app">
<button @click="changeName2('小浪')">方式1 按钮使用 action 中方法</button>
{{ name }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState mapMutations
import { mapState, mapMutations } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
},
methods: {
changeName2(newName) {
// 使用 dispatch 来调用 actions 中的方法
this.$store.dispatch('changeNameAsync', newName)
}
},
}
</script>
<style scoped>
</style>
复制代码
2.使用 mapActions
<template>
<div id="app">
<button @click="changeNameAsync('小浪')">
方式2 按钮使用 action 中方法
</button>
{{ name }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState mapMutations mapActions
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
},
methods: {
// 映射 actions 中的指定方法 到 methods中,就可以在该组件直接使用
...mapActions(['changeNameAsync'])
},
}
</script>
<style scoped>
</style>
复制代码
4.Getter
简介
Getter
类似于计算属性,但是我们的数据来源是 Vuex
中的 state
,所以就使用 Vuex
中的 Getter
来完成
应用场景
需要对 state
做一些包装简单性处理 展示到视图当中
先来写个 Getter
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
getters: {
// 在这里对 状态 进行包装
/**
*
* @param {*} state 状态 如果要使用 state 里面的数据,第一个参数默认就是 state ,名字随便取
* @returns
*/
decorationName(state) {
return `大家好我的名字叫${state.name}今年${state.age}岁`
},
},
})
复制代码
当然 Getter
也有两种方式导入
1.this.$store.getters[名称]
<template>
<div id="app">
{{ this.$store.getters.decorationName }}
</div>
</template>
复制代码
2.使用 mapGetters
<template>
<div id="app">
{{ decorationName }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapGetters
import { mapGetters } from 'vuex'
export default {
name: 'App',
computed: {
// 将 getter 映射到当前组件的计算属性
...mapGetters(['decorationName'])
},
}
</script>
复制代码
5.Module
为了避免在一个复杂的项目 state
中的数据变得臃肿,Vuex
允许将 Store
分成不同的模块,每个模块都有属于自己的 state
,getter
,action
,mutation
我们这里新建一个
animal.js
文件
/* animal.js */
const state = {
animalName: '狮子',
}
const mutations = {
setName(state, newName) {
state.animalName = newName
},
}
//导出
export default {
state,
mutations,
}
复制代码
在
store/index.js
中的modules
进行挂载这个模块
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 引入模块
import animal from './animal'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
animal,
},
})
复制代码
然后我们就可以在组件中使用了
<template>
<div id="app">
{{ this.$store.state.animal.animalName }}
<button @click="$store.commit('setName', '老虎')">改名</button>
</div>
</template>
复制代码
$store.state[在module中挂载的模块名][挂载的模块里的属性]
是不是觉得这种模式很复杂
添加命名空间
其实也可以使用 mapXXX
方法进行映射,不过写法有些许不同,先在导出的添加一个命名空间 namespaced: true
/* animal.js */
const state = {
animalName: '狮子',
}
const mutations = {
setName(state, newName) {
state.animalName = newName
},
}
export default {
// 开启命名空间 方便之后使用 mapXXX
namespaced: true,
state,
mutations,
}
复制代码
方式2
<template>
<div id="app">
{{ animalName }}
<button @click="setName('老鹰')">改名</button>
</div>
</template>
<script>
// 从 Vuex 中导入 mapState mapMutations
import { mapState, mapMutations } from 'vuex'
export default {
name: 'App',
computed: {
// mapState 使用方式和之前有些许不同,第一个是module挂载的模块名
// 第二个参数是 animal 模块中的 state 属性
...mapState('animal', ['animalName'])
},
methods: {
// mapMutations 使用方式也和之前有些许不同,第一个是module挂载的模块名
// 第二个参数是 animal 模块中的 mutation 方法
...mapMutations('animal', ['setName'])
},
}
</script>
复制代码
3.模拟一个简单的Vuex
上面我们已经介绍了 Vuex
的基本使用,现在我们来自己动手写个简单 Vuex
代码我都会写满注释方便大家观看,代码很少,有兴趣,大家耐心观看 ヽ( ̄▽ ̄)ノ
1.index.js
先搭个基本的架子
我们在 src
目录下 建立一个属于我们自己的 Vuex
的文件夹,并且在这个目录下添加一个 index.js
文件,我们要模拟的这个 Vuex
就会放在这里面
/* my-vuex/index.js */
// 保存一个全局的 Vue 之后会用到
let _Vue = null
// Store 类
class Store {
// 先完成构造方法,构造方法接收一个对象
constructor(options) {
//...待实现
}
}
// 因为Vuex 需要 Vue.use() 安装,所以我们必须要有个 install 方法 传入 Vue
// 第二个参数是一个可选对象
function install(Vue) {
//... 待实现
}
// 导出 install 和 Store
export default {
install,
Store,
}
复制代码
2.install方法
因为Vuex 插件 需要 Vue.use() 安装,所以我们必须要有个 install 方法,第一个参数 传入 Vue
// 第二个参数是一个可选对象
function install(Vue) {
// 保存到全局 _Vue
_Vue = Vue
// 全局注册混入 这样在所有的组件都能使用 $store
_Vue.mixin({
// beforeCreate vue初始化阶段
// 在 beforeCreate 这个时候把 $store 挂载到 Vue 上
beforeCreate() {
// 判断 Vue 传递的对象是否有 store 需要挂载
// this.$options 是new Vue() 传递的对象
if (this.$options.store) {
// 把 store 挂载到 Vue 原型上
_Vue.prototype.$store = this.$options.store
}
},
})
}
复制代码
3.我们继续来实现
Store
类
先完成基础的 构造方法
/* my-vuex/index.js */
// 保存一个全局的 Vue 之后会用到
let _Vue = null
// Store 类
class Store {
// 先完成构造方法,构造方法接收一个对象
constructor(options) {
// 赋初值
const state = options.state || {}
const mutations = options.mutations || {}
const actions = options.actions || {}
const getters = options.getters || {}
}
//...install
复制代码
接着,我们来实现 state
,getters
,mutations
,actions
,commit
,dispatch
吧
( ゚▽゚)/
3.state
是不是超简单,直接调用 Vue
的 observable
把 state
变成响应式
/* my-vuex/index.js */
// Store 类
class Store {
constructor(options) {
//...其他细节
// 1.实现state 把 state 中的数据转为 响应式,直接用 Vue 中的 observable
this.state = _Vue.observable(state)
}
}
复制代码
4.getters
为每一个 getters
里面的 方法添加了一个 get
/* my-vuex/index.js */
// Store 类
class Store {
constructor(options) {
//...其他细节
// 2.实现 getters 这里为什么不知直接 把this.getters 赋值 {} 而是 Object.create(null)
// 好处是不用考虑会和原型链上的属性重名问题
this.getters = Object.create(null)
// 我们要为 getters 添加一个 get 方法,这里就要使用 数据劫持
// 先拿到 getters 中每一个 方法
Object.keys(getters).forEach((key) => {
// 第一个参数是给谁添加 ,第二个是添加的属性名,第三个对象里面可以设置很多参数
// 比如 可枚举,可配置,get,set
Object.defineProperty(this.getters, key, {
// 为 this.getters 每一项都添加 一个 get 方法
get: () => {
// 还记得吗,getters 中的方法 默认把 state传入进去,改变this指向
return getters[key].call(this, this.state)
},
})
})
}
}
复制代码
5.mutations
这里改变 this
指向
/* my-vuex/index.js */
// Store 类
class Store {
constructor(options) {
//...其他细节
// 3.实现 mutations
// 先遍历 mutaions 中的对象进行改变 this指向
this.mutations = {}
Object.keys(mutations).forEach((key) => {
this.mutations[key] = (params) => {
// 改变this指向 ,默认是要传入 state
mutations[key].call(this, this.state, params)
}
})
}
}
复制代码
6.actions
其实呢,和上面的 mutations
处理方式差不多,不过参数 传递的不一样,需要传递 上下文 context
也就是 Store
的一个实例,这里就是 this
/* my-vuex/index.js */
// Store 类
class Store {
constructor(options) {
//...其他细节
// 4.实现 actions
// 和 mutations 一样我们需要重新改变 this 指向
this.actions = {}
Object.keys(actions).forEach((key) => {
this.actions[key] = (params) => {
// 改变this指向 ,默认是要传入 store也就是 this
actions[key].call(this, this, params)
}
})
}
}
复制代码
7.commit
/* my-vuex/index.js */
// Store 类
class Store {
constructor(options) {
//...其他细节
}
// 5.实现commit 方法
// 用于 触发mutations中的方法
// 第一个参数是事件名 ,第二个是参数
commit = (eventName, params) => {
this.mutations[eventName](params)
}
}
复制代码
8.dispatch
dispatch
和 commit
实现差不多
/* my-vuex/index.js */
// Store 类
class Store {
constructor(options) {
//...其他细节
}
// 6.实现 dispatch 方法
// 用于 触发actions中的异步方法
// 第一个参数是事件名 ,第二个是参数
dispatch = (eventName, params) => {
this.actions[eventName](params)
}
}
复制代码
好了,到了这里差不多,一个丐版的 Vuex
就这样诞生了,我们写个例子去测试下吧
9.测试例子
先导入我们自己写的
Vuex
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 我们自己写的 Vuex 插件
import Vuex from '../my-vuex/index'
// 把 Vuex 安装到到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {
changeName(state, newName) {
// 这里简单举个例子 修改个名字
state.name = newName
},
},
actions: {
changeNameAsync(context, newName) {
// 这里用 setTimeout 模拟异步
setTimeout(() => {
// 在这里调用 mutations 中的处理方法
context.commit('changeName', newName)
}, 2000)
},
},
getters: {
decorationName(state) {
return `大家好我的名字叫${state.name}今年${state.age}岁`
},
},
})
复制代码
一个简单的
vue
组件
<template>
<div id="app">
<h1>我是 state 测试:{{ this.$store.state.name }}</h1>
<h1>我是 getters 测试:{{ this.$store.getters.decorationName }}</h1>
<button @click="$store.commit('changeName', 'mutations 按钮')">
mutations 按钮
</button>
<button @click="$store.dispatch('changeNameAsync', 'actions 按钮')">
actions 按钮
</button>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style scoped>
</style>
复制代码
在 mian.js 还是之前一样的挂载没改
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
// 挂载到vue 中
store,
render: (h) => h(App),
}).$mount('#app')
复制代码
例子预览
到了这里并不是结束了,不如简单实现一下 几个 mapXXX
,实现起来都差不多
10.mapSate
...mapSate(['age',['name']])
,最后 computed
得到的就是 age
: 21
, name
: '张三'
这样,就可以在 组件中直接使用了
const mapState = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function() {
return this.$store.state[item]
}
})
return obj
}
复制代码
11.mapMutations
const mapMutations = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function(params) {
return this.$store.commit(item, params)
}
})
return obj
}
复制代码
12.mapActions
const mapActions = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function(params) {
return this.$store.dispatch(item, params)
}
})
return obj
}
复制代码
13.mapGetters
const mapGetters = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function() {
return this.$store.getters[item]
}
})
return obj
}
复制代码
14.导出和使用
最后就是导出
// 导出
export { mapState, mapMutations, mapActions, mapGetters }
复制代码
使用方法和之前一样
<template>
<div id="app">
<button @click="changeName('狗子')">mapMutations</button>
<button @click="changeNameAsync('狗2子')">mapMutations</button>
{{ decorationName }}
{{ age }}
</div>
</template>
<script>
// 导入
import { mapState, mapMutations, mapActions, mapGetters } from './my-vuex/index'
export default {
name: 'App',
computed: {
...mapState(['age']),
...mapGetters(['decorationName'])
},
methods: {
...mapMutations(['changeName']),
...mapActions(['changeNameAsync'])
},
}
</script>
...
</style>
复制代码
3.结语
好了到了这里,关于 Vuex
本文就结束了,我们从 Vuex
是啥,怎么使用,动手实现一个简单 Vuex
我们都完成了,希望大家有所收获
下面把完成的我们模拟的 Vuex
代码贴出,欢迎大家,多多交流,有什么写错的地方,请大家指出
模拟 Vuex
完整代码
/* my-vuex/index.js */
// 保存一个全局的 Vue 之后会用到
let _Vue = null
// Store 类
class Store {
// 先完成构造方法,构造方法接收一个对象
constructor(options) {
// 赋初值
const state = options.state || {}
const mutations = options.mutations || {}
const actions = options.actions || {}
const getters = options.getters || {}
// 1.实现state 把 state 中的数据转为 响应式,直接用 Vue 中的 observable
this.state = _Vue.observable(state)
// 2.实现 getters 这里为什么不知直接 把this.getters 赋值 {} 而是 Object.create(null)
// 好处是不用考虑会和原型链上的属性重名问题
this.getters = Object.create(null)
// 我们要为 getters 添加一个 get 方法,这里就要使用 数据劫持
// 先拿到 getters 中每一个 方法
Object.keys(getters).forEach((key) => {
// 第一个参数是给谁添加 ,第二个是添加的属性名,第三个对象里面可以设置很多参数
// 比如 可枚举,可配置,get,set
Object.defineProperty(this.getters, key, {
// 为 this.getters 每一项都添加 一个 get 方法
get: () => {
// 还记得吧,getters 中的方法 默认把 state传入进去,改变this指向
return getters[key].call(this, this.state)
},
})
})
// 3.实现 mutations
// 先遍历 mutaions 中的对象进行改变 this指向
this.mutations = {}
Object.keys(mutations).forEach((key) => {
this.mutations[key] = (params) => {
// 改变this指向 ,默认是要传入 state
mutations[key].call(this, this.state, params)
}
})
// 4.实现 actions
// 和 mutations 一样我们需要重新改变 this 指向
this.actions = {}
Object.keys(actions).forEach((key) => {
this.actions[key] = (params) => {
// 改变this指向 ,默认是要传入 store也就是 this
actions[key].call(this, this, params)
}
})
}
// 5.实现commit 方法
// 用于 触发mutations中的方法
// 第一个参数是事件名 ,第二个是参数
commit = (eventName, params) => {
this.mutations[eventName](params)
}
// 6.实现 dispatch 方法
// 用于 触发actions中的异步方法
// 第一个参数是事件名 ,第二个是参数
dispatch = (eventName, params) => {
this.actions[eventName](params)
}
}
// 因为Vuex 需要 Vue.use() 安装,所以我们必须要有个 install 方法 传入 Vue
// 第二个参数是一个可选对象
function install(Vue) {
// 保存到全局 _Vue
_Vue = Vue
// 全局注册混入 这样在所有的组件都能使用 $store
_Vue.mixin({
// beforeCreate vue初始化阶段
// 在 beforeCreate 这个时候把 $store 挂载到 Vue 上
beforeCreate() {
// 判断 Vue 传递的对象是否有 store 需要挂载
// this.$options 是new Vue() 传递的对象
if (this.$options.store) {
// 把 store 挂载到 Vue 原型上
_Vue.prototype.$store = this.$options.store
}
},
})
}
// mapState
const mapState = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function() {
return this.$store.state[item]
}
})
return obj
}
// mapMutations
const mapMutations = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function(params) {
return this.$store.commit(item, params)
}
})
return obj
}
// mapActions
const mapActions = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function(params) {
return this.$store.dispatch(item, params)
}
})
return obj
}
// mapGetters
const mapGetters = (params) => {
// 这里我只写个数组的 起别名的就没弄哈
if (!Array.isArray(params))
throw new Error('抱歉,当前是丐版的Vuex,只支持数组参数')
// 第一步就是要初始 obj ,不然[item] 会报错
let obj = {}
// 实现逻辑很简单,就是接收传递的的参数
// 去this.$store寻找
params.forEach((item) => {
obj[item] = function() {
return this.$store.getters[item]
}
})
return obj
}
// 导出
export { mapState, mapMutations, mapActions, mapGetters }
// 导出 install 和 store
export default {
install,
Store,
}
复制代码