0%

Vuex

安装Vuex

1
npm install vuex --save

新建文件

新建一个store文件夹,在文件夹下面新建index.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

import Vue from 'vue'
import Vuex from 'vuex'

// 使用vuex
Vue.use(Vuex)

const state = {
count:1
}
const mutations = {

}
const getters = {

}
const actions = {

}
const modules = {

}
// 导出 让外部可以引用
export default new Vuex.Store({
state,
mutations,
getters,
actions
})

基本使用

main.js中引入store/index.js文件

1
2
3
4
5
6
7
8
9
10
11
12
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

添加修改state中值的方法

store/index.js文件,mutations方法中设置方法

1
2
3
4
5
6
7
8
const mutations = {
add(state){
state.count++
},
reduce(state){
state.count--
}
}

在模板中添加调用mutations里面设置的方法

1
2
3
4
5
6
7
<template>
<div class="hello">
<p>store值:{{$store.state.count}}</p>
<button @click="$store.commit('add')"></button> |
<button @click="$store.commit('reduce')"></button>
</div>
</template>

state访问状态对象

访问state状态对象中的的方式有好几种,

  • 方式一:通过computed访问
    1
    2
    3
    4
    5
    computed:{
    newCount() {
    return this.$store.state.count
    }
    }
  • 方式二:通过mapState访问
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 需要引入mapState
    import {mapState} from 'vuex';

    // 写法一:
    computed:{
    ...mapState(["count"])
    }

    // 写法二:
    computed:{
    ...mapState({
    count:state=>state.count
    })
    }

    mutations修改状态

    获取Mutations里面的方法:
  • 方法一:mutations修改states中的值
    1
    2
    <button @click="$store.commit('add')">加</button> | 
    <button @click="$store.commit('reduce')">减</button>
    如果需要传参数,可以如下传参写法
    1
    2
    <button @click="$store.commit('add', 100)">加</button> | 
    <button @click="$store.commit('reduce')">减</button>
    /store/index.js文件中,data就是触发方法时候的参数
    1
    2
    3
    4
    5
    6
    7
    8
    const mutations = {
    add(state,data){
    state.count +=data
    },
    reduce(state){
    state.count--
    }
    }
  • 方法二:
    首先引入mapMutations
    1
    import {mapState,mapMutations} from 'vuex';
    模板中写法
    1
    2
    <button @click="add(100)"></button> | 
    <button @click="reduce"></button>

    getters操作

    getters操作是在获取数据之前进行的一种再编辑,相当于对数据的一个过滤和加工,可以把它看作index.js的计算属性。
    写法如下:
    1
    2
    3
    4
    5
    const getters = {
    getterCount(state){
    return state.count+10000
    }
    }
    使用:
    方法一:
    1
    <div>{{$store.getters.getterCount}}</div>
    方法二:
    1
    2
    3
    4
    5
    import {mapState,mapMutations,mapGetters} from 'vuex';

    computed:{
    ...mapGetters(['getterCount'])
    }
    方法三:
    1
    2
    3
    4
    5
    computed:{
    getterCount(){
    return this.$store.getters.getterCount
    }
    }

    actions异步修改状态

    如果需要执行异步操作,就使用action,当异步操作完成,如果修改状态状态,再调用mutations修改状态,因为所有的状态修改都需要mutations,下面例子:
    store/index.js文件中
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const actions = {
    // 两个参数
    // 参数1:上下文,有所有需要的state,commit, getters等成员
    // 参数2:额外的数据,传值用的
    addAsync(context,payload){
    console.log(context)
    // 延时调用mutations
    setTimeout(function(){
    context.commit('add',payload)
    },2000)
    }
    }
    context文中内容
    action上下文
    模板中使用
    方法一:
    1
    2
    // 这里的dispatch是action的固定用法,就好比mutation中的commit
    <button @click="$store.dispatch('addAsync',9999)">Action</button>
    方法二:
    1
    2
    3
    4
    5
    6
    7
    <button @click="addAsync(9999)">Action</button>

    import {mapState,mapMutations,mapGetters,mapActions} from 'vuex';

    methods:{
    ...mapActions(['addAsync'])
    }

    module模块

    可以将单一状态拆分成多个模块,每个模块都可以有自己的statemutationaction等,一般当状态特别多的时候才会用,在store文件夹下创建一个module文件夹,在里面建a.jsb.js文件.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// a.js文件
const state = {
a_module:1
}
const mutations = {

}
const getters = {

}
const actions = {

}
export default {
state,
mutations,
getters,
actions
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// b.js
const state = {
b_module:1
}
const mutations = {

}
const getters = {

}
const actions = {

}
export default {
state,
mutations,
getters,
actions
}

index.js中引入模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import a from './module/a'
import b from './module/b'

const modules = {
a,
b
}
// 导出 让外部可以引用
export default new Vuex.Store({
state,
mutations,
getters,
actions,
modules
})

使用:

1
<div>{{$store.state.a.a_module}}</div>

开启命名空间

1
2
3
4
5
6
7
8
// a.js 和 b.js
export default {
namespaced: true,
state,
mutations,
getters,
actions
}

index.js注册引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import a from './module/a'
import b from './module/b'

const modules = {
a,
b
}
// 导出 让外部可以引用
export default new Vuex.Store({
state,
mutations,
getters,
actions,
modules
})

模板中使用

1
2
3
4
5
6
7
8
9
import {mapState,mapMutations,mapGetters,mapActions} from 'vuex';
computed:{
// 参数1: 命名空间名字,
// 参数2: 状态名
...mapState('a',['a_module'])
}
methods:{
...mapActions('命名空间名',['mutations方法名'])
}

Vuex插件

  • Vuex的插件就是一个函数
  • 这个函数接收一个store的参数

Vuex插件使用

1
2
3
4
5
6
7
const myPlugin = store => {
// store 初始化
store.subscribe( (mutation, state)=>{
// 每次mutation之后调用
// mutation的格式为{type,payload}
})
}
1
2
3
const store = new Vuex.Store({
plugins: [myPlugin]
})

简单模拟Vuex

基本机构

1
2
3
4
5
6
7
8
9
10
11
let _Vue = null
class Store {}

function install(Vue){
_Vue = Vue
}

export default {
Store,
install
}

install

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let _Vue = null
class Store {}

function install(Vue){
_Vue = Vue
// intall中获取不到vue根实例,通过混入来获取vue实例
_Vue.mixin({
beforeCreate() {
// 判断当前vue实例的$options中是否是store,
// 如果是组件实例,没有store选项,就不需要做这件事情
if(this.$options.store){
_Vue.prototype.$store = this.$options.store
}
}
})
}
export default {
Store,
install
}

store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
let _Vue = null
class Store {
// 构造函数
constructor(options){
// options成员解构出来,
// 为了用户创建vuex时候,没有传入相应的选项,设置了一个默认值{}
const {
state = {},
getters = {},
mutations = {},
actions = {}
} = options
// 因为state是响应式的,响应式处理
this.state = _Vue.observable(state)
// getters是一个对象,对象中有一些方法,
// 这些方法都需要state参数,并且都有返回值,
// 也就是对state做一些处理,然后将处理的结果返回
this.getters = Object.create(null)
Object.keys(getters).forEach(key=>{
// 通过defineProperty 转成了getters访问器,这里key就是方法的名字
Object.defineProperty(this.getters,key,{
// 返回key在getters中的到的方法调用的结果
get:()=>getters[key](state)
})
})
// 将mutations 和 actions存到对应的属性中,在commit和dispatch中获取
this._mutations = mutations
this._actions = actions
}
// 参数1:_mutations中方法的名字
// 参数2:调用方法时传入的参数
commit (type, payload){
this._mutations[type](this.state,payload)
}
// 参数1:_actions中方法的名字
// 参数2:调用方法时传入的参数
dispatch(type,payload){
this._actions[type](this,payload)
}
}

function install(Vue){
_Vue = Vue
// intall中获取不到vue根实例,通过混入来获取vue实例
_Vue.mixin({
beforeCreate() {
// 判断当前vue实例的$options中是否是store,
// 如果是组件实例,没有store选项,就不需要做这件事情
if(this.$options.store){
_Vue.prototype.$store = this.$options.store
}
}
})
}

export default {
Store,
install
}
--------- 本文结束感谢您的阅读 ---------
分享