组成
- state:状态
- mutation:原子级修改状态
- action:调用mutation
- getter:状态的computed
环境搭建
- npm install --global vue-cli@3.10.0
- 通过
vue create vuex创建项目,手动选择配置,只选上babel和vuex - 打开啊vuex项目,目录结构如下
这个index.js文件如下:
import Vue from 'vue'
// 使用了npm 下载的vuex
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
我们在store文件夹下新建一个myVuex.js文件实现vuex功能,
在index.js中使用myVuex.js,并给出一个基础的vuex配置
import Vue from 'vue'
// 使用了npm 下载的vuex
// import Vuex from 'vuex'
// 换成我们自己写的
import Vuex from './myVuex.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
a:1,
b:2
},
getters: {
add(state){
return state.a + state.b
}
},
mutations: {
changeA(state,newValue){
state.a = newValue
}
},
actions: {
changeAAfterOneSec(context,newValue){
setTimeout(() => {
context.commit('changeA',newValue)
}, 1000);
}
},
modules: {
}
})
挺简单的,两个state、一个mutation、一个action
设计myVuex
打开store/myVuex.js文件
// 引入vue,等下有用
import vue from 'vue'
// 因为vuex是通过vue.use(Vuex)作为vue插件使用的,所以我们得导出一个install方法
function install(Vue) {
// 全局的Vue对象,我们混入一些东西
Vue.mixin({
// 因为在beforeCreate阶段能拿到this.$options对象,而根Vue中有vuex创建出来的store对象,我们将它绑定到this.$store中,这样组件内才能通过this.$store去访问store
beforeCreate() {
// 如果是根结点
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} // 如果不是根结点,则将父组件的$store绑定过来
else {
this.$store = this.$parent && this.$parent.$store
}
},
})
}
// 设计vuex,首先store是一个类
class Store{
constructor(options){
// options是vuex的配置,在上面的代码块中可查看
let state = options.state || {}
let getters = options.getters || {}
let mutations = options.mutations || {}
let actions = options.actions || {}
// 对于this.state,我们肯定是要将其属性设计成响应式的
// 有两种实现方式,这边只说最简单的,通过vue自带的一个方法来实现
this.state = vue.observable(state)
// 对于this.gettters,我们在vuex的配置中是通过方法来定义的
// getters: {
// add(state){
// return state.a + state.b
// }
// },
// 我们在组件中通过$store.getters.add来访问
// 所以我们得通过属性描述符的get来实现
this.getters = {}
for(let key in getters){
let getter = getters[key]
Object.defineProperty(this.getters,key,{
get:()=>{
getter(this.state)
}
})
}
// 对于this.mutations,我们在vuex的配置中是通过方法来定义的
// mutations: {
// changeA(state,newValue){
// state.a = newValue
// }
// },
// 我们在组件中通过$store.commit('changeA',3)来访问
// 我们先将配置中的mutations放入this.mutations
this.mutations = {}
for(let key in mutations){
let mutation = mutations[key]
this.mutations[key] = (args)=>{
return mutation(this.state,args)
}
}
this.commit = (mutationName,args)=>{
return this.mutations[mutationName](args)
}
// 对于this.actions,我们在vuex的配置中是通过方法来定义的
// actions: {
// changeAAfterOneSec(context,newValue){
// setTimeout(() => {
// context.commit('changeA',newValue)
// }, 1000);
// }
// },
// 我们在组件中通过$store.disptach('changeAAfterOneSec',3)来访问
// 我们先将配置中的actions放入this.actions
this.actions = {}
for(let key in actions){
let action = actions[key]
this.actions[key] = (args)=>{
return action(this,args)
}
}
this.commit = (actionName,args)=>{
return this.actions[actionName](args)
}
}
}
export default {
install,
Store
}
设计mapState、mapGetters、mapMutations、mapActions
我们一般通过以下方式使用这四个辅助函数
import {mapState,mapGetters,mapMutations,mapActions}
export default {
data(){
return {}
},
computed:{
...mapState(['a','b']),
...mapGetter(['add']),
},
methods:{
...mapMutations(['changeA']),
...mapActions(['changeAAfterOneSec']),
}
}
设计
import vue from 'vue'
function install(Vue) {
....
}
// 设计vuex,首先store是一个类
class Store{
...
}
function mapState(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = () => this.$store.state[item]
}
return obj
}
function mapGetters(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = () => this.$store.getters[item]
}
return obj
}
function mapMutations(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = (args)=>{this.$store.mutations[item](args)}
}
return obj
}
function mapActions(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = (args)=>{this.$store.actions[item](args)}
}
return obj
}
export default {
install,
Store,
mapState,
mapGetters,
mapMutations,
mapActions
}
整体代码
// 引入vue,等下有用
import vue from 'vue'
// 因为vuex是通过vue.use(Vuex)作为vue插件使用的,所以我们得导出一个install方法
function install(Vue) {
// 全局的Vue对象,我们混入一些东西
Vue.mixin({
// 因为在beforeCreate阶段能拿到this.$options对象,而根Vue中有vuex创建出来的store对象,我们将它绑定到this.$store中,这样组件内才能通过this.$store去访问store
beforeCreate() {
// 如果是根结点
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} // 如果不是根结点,则将父组件的$store绑定过来
else {
this.$store = this.$parent && this.$parent.$store
}
},
})
}
// 设计vuex,首先store是一个类
class Store{
constructor(options){
// options是vuex的配置,在上面的代码块中可查看
let state = options.state || {}
let getters = options.getters || {}
let mutations = options.mutations || {}
let actions = options.actions || {}
// 对于this.state,我们肯定是要将其属性设计成响应式的
// 有两种实现方式,这边只说最简单的,通过vue自带的一个方法来实现
this.state = vue.observable(state)
// 对于this.gettters,我们在vuex的配置中是通过方法来定义的
// getters: {
// add(state){
// return state.a + state.b
// }
// },
// 我们在组件中通过$store.getters.add来访问
// 所以我们得通过属性描述符的get来实现
this.getters = {}
for(let key in getters){
let getter = getters[key]
Object.defineProperty(this.getters,key,{
get:()=>{
getter(this.state)
}
})
}
// 对于this.mutations,我们在vuex的配置中是通过方法来定义的
// mutations: {
// changeA(state,newValue){
// state.a = newValue
// }
// },
// 我们在组件中通过$store.commit('changeA',3)来访问
// 我们先将配置中的mutations放入this.mutations
this.mutations = {}
for(let key in mutations){
let mutation = mutations[key]
this.mutations[key] = (args)=>{
return mutation(this.state,args)
}
}
this.commit = (mutationName,args)=>{
return this.mutations[mutationName](args)
}
// 对于this.actions,我们在vuex的配置中是通过方法来定义的
// actions: {
// changeAAfterOneSec(context,newValue){
// setTimeout(() => {
// context.commit('changeA',newValue)
// }, 1000);
// }
// },
// 我们在组件中通过$store.disptach('changeAAfterOneSec',3)来访问
// 我们先将配置中的actions放入this.actions
this.actions = {}
for(let key in actions){
let action = actions[key]
this.actions[key] = (args)=>{
return action(this,args)
}
}
this.commit = (mutationName,args)=>{
return this.mutations[mutationName](args)
}
}
}
function mapState(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = () => this.$store.state[item]
}
return obj
}
function mapGetters(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = () => this.$store.getters[item]
}
return obj
}
function mapMutations(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = (args)=>{this.$store.mutations[item](args)}
}
return obj
}
function mapActions(arr){
let obj = {}
for(let i = 0;i<arr.length;i++){
let item = arr[i]
obj[item] = (args)=>{this.$store.actions[item](args)}
}
return obj
}
export default {
install,
Store,
mapState,
mapGetters,
mapMutations,
mapActions
}