vuex基本使用方式
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//统一状态管理
state: {
name: '李明'
},
//状态更改
mutations: {},
//异步提交更改
actions: {},
modules: {}
})
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div id="app">
{{$store.state}}
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
输出:
分析vuex结构
打印Vuex:
打印Vue实例:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
let vm = new Vue({
store,
render: h => h(App),
}).$mount('#app')
console.dir(vm)
可见,store绑定在$options
中。
可见,$store
绑定在Vue实例中,因此可以通过获取 $options
的store,绑定给$store
。
vuex源码实现
1、创建基本结构
vuex/index.js
const install = (_Vue) => {
console.log(_Vue)
}
class Store {
}
export default {
install,
Store,
}
Vue.use(Vuex)
会调用install,因此需要创建install方法。
store.js使用了new Vuex.Store
,因此需要创建Store类。
输出_Vue(Vue.use在调用install方法时传入参数_Vue):
注意:
这里使用_Vue获取Vue实例而不是使用import,因为main.js也导入了Vue,如果使用import,会打包多次。
2、实现数据传递:state
const install = (_Vue) => {
let Vue = _Vue;
// console.dir(Vue)
//给所有组件添加共同的功能
Vue.mixin({
//这里是为了在组件创建之前,给其传入数据
beforeCreate() {
//判断组件自身是否存在store
if (this.$options && this.$options.store) this.$store = this.$options.store;
//不存在则寻找父组件的$store(需要加$)
else this.$store = this.$parent && this.$parent.$store;
},
})
}
class Store {
constructor(options = {}) {
//参数赋值
this.state = options.state;
}
}
export default {
install,
Store,
}
3、实现状态修改:mutations
export default new Vuex.Store({
//统一状态管理
state: {
name: '李明',
age: 18,
},
//状态更改
mutations: {
//年龄增加
addAge(state, payload) {
state.age += payload;
}
},
//异步提交更改
actions: {},
modules: {}
})
<template>
<div id="app">
姓名:{{$store.state.name}}<br>
年龄:{{$store.state.age}}<br>
<button @click="add">长一岁</button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods:{
add() {
this.$store.commit('addAge',1);
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
class Store {
constructor(options = {}) {
//参数赋值
this.state = options.state;
this.mutations = options.mutations;
}
//提交修改
commit(mutationName, payload) {
//遍历mutations绑定的所有方法名称
Object.keys(this.mutations).forEach(name => {
//如果和传入的方法名称相同,则调用
if (mutationName === name) this.mutations[mutationName](this.state, payload);
});
}
}
这里可以看到,虽然$store.state.age
已经被修改,但是视图依然没有更新,因此可以将其添加到Vue的data中,实现双向绑定。
let Vue;
const install = (_Vue) => {
Vue = _Vue;
//给所有组件添加共同的功能
Vue.mixin({
//这里是为了在组件创建之前,给其传入数据
beforeCreate() {
//判断组件自身是否存在store
if (this.$options && this.$options.store) this.$store = this.$options.store;
//不存在则寻找父组件的$store(需要加$)
else this.$store = this.$parent && this.$parent.$store;
},
})
}
class Store {
constructor(options = {}) {
//实现双向绑定
let v = new Vue({
data() {
return {
state: options.state,
mutations: options.mutations,
}
},
});
//参数赋值
this.state = v.state;
this.mutations = v.mutations;
}
//提交修改
commit(mutationName, payload) {
//遍历mutations绑定的所有方法名称
Object.keys(this.mutations).forEach(name => {
//如果和传入的方法名称相同,则调用
if (mutationName === name) this.mutations[mutationName](this.state, payload);
});
}
}
export default {
install,
Store,
}
4、实现异步状态修改:action
import Vue from 'vue'
import Vuex from 'vuex'
//调用install
Vue.use(Vuex)
export default new Vuex.Store({
//统一状态管理
state: {
name: '李明',
age: 18,
},
//状态更改
mutations: {
//年龄增加
addAge(state, payload) {
state.age += payload;
}
},
//异步提交更改
actions: {
//异步年龄增加
asyncAddAge({ commit }, payload) {
setTimeout(() => {
commit('addAge', payload);
}, 1000);
}
},
modules: {}
})
<template>
<div id="app">
姓名:{{$store.state.name}}<br>
年龄:{{$store.state.age}}<br><br>
<button @click="add">长一岁</button><br><br>
<button @click="asyncAdd">1秒后长一岁</button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods:{
add() {
this.$store.commit('addAge',1);
},
asyncAdd() {
this.$store.dispatch('asyncAddAge',1);
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
let Vue;
const install = (_Vue) => {
Vue = _Vue;
//给所有组件添加共同的功能
Vue.mixin({
//这里是为了在组件创建之前,给其传入数据
beforeCreate() {
//判断组件自身是否存在store
if (this.$options && this.$options.store) this.$store = this.$options.store;
//不存在则寻找父组件的$store(需要加$)
else this.$store = this.$parent && this.$parent.$store;
},
})
}
class Store {
constructor(options = {}) {
//实现双向绑定
let v = new Vue({
data() {
return {
state: options.state,
mutations: options.mutations,
actions: options.actions,
}
},
});
//参数赋值
this.state = v.state;
this.mutations = v.mutations;
this.actions = v.actions;
}
//提交修改
commit = (mutationName, payload) => {
//遍历mutations绑定的所有方法名称
Object.keys(this.mutations).forEach(name => {
//如果和传入的方法名称相同,则调用
if (mutationName === name) this.mutations[mutationName](this.state, payload);
});
}
//异步提交修改
dispatch = (actionName, payload) => {
//遍历actions绑定的所有方法名称
Object.keys(this.actions).forEach(name => {
if (actionName === name) this.actions[actionName]({ commit: this.commit }, payload);
})
}
}
export default {
install,
Store,
}
注意:
这里方法格式需要写成xxx = () => {}
,否则会出现this指向underfined的问题。
5、实现数据获取:getters
store/index.js
getters: {
getName(state) {
return state.name;
}
}
App.vue
姓名:{{$store.getters.getName}}
let Vue;
const install = (_Vue) => {
Vue = _Vue;
//给所有组件添加共同的功能
Vue.mixin({
//这里是为了在组件创建之前,给其传入数据
beforeCreate() {
//判断组件自身是否存在store
if (this.$options && this.$options.store) this.$store = this.$options.store;
//不存在则寻找父组件的$store(需要加$)
else this.$store = this.$parent && this.$parent.$store;
},
})
}
class Store {
constructor(options = {}) {
//实现双向绑定
let v = new Vue({
data() {
return {
state: options.state,
mutations: options.mutations,
actions: options.actions,
getters: options.getters,
}
},
});
//参数赋值
this.state = v.state;
this.mutations = v.mutations;
this.actions = v.actions;
this.getters = {};
//定义getters
Object.keys(v.getters).forEach(name => {
Object.defineProperty(this.getters, name, {
get: () => {
return v.getters[name](this.state);
}
})
})
}
//提交修改
commit = (mutationName, payload) => {
//遍历mutations绑定的所有方法名称
Object.keys(this.mutations).forEach(name => {
//如果和传入的方法名称相同,则调用
if (mutationName === name) this.mutations[mutationName](this.state, payload);
});
}
//异步提交修改
dispatch = (actionName, payload) => {
//遍历actions绑定的所有方法名称
Object.keys(this.actions).forEach(name => {
if (actionName === name) this.actions[actionName]({ commit: this.commit }, payload);
})
}
}
export default {
install,
Store,
}