一 使用
1.1安装:npm install vuex --save
1.2在src目录下创建一个store文件夹并在store文件夹下创建一个index.js文件
文件内容如下
import Vuex from'vuex';
import Vue from 'vue';
Vue.use(Vuex);
//创建仓库
const store Vuex.Store({
//数据
state: {
test_data: “this is some test data”,
color: “light-green”
},
//修改值得方法
mutations: {
setColor(state, coLor) {
state.color= color;
},
Action:{
login({commit}, username) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (username === 'admin') {
commit('setColor',res.data.data)//调用上方mutations中setColor方法修改数据
resolve()
} else {
reject()
}
}, 1000);
})
}
},
modules: {//模块化使用modules定义多个子模块利于组件复杂状态
user,
}
}
export default store
1.3:main.js加载和挂载
import stort from './store/index'
new Vue({
el: ‘#app’,
router,
store,
components: { App },
template: ‘<App!>’
})
1.4:使用
① 修改
//第一个参数为mutations下的方法,二为参数
//不用加载任何vuex的文件main.js中已经全局加载了
this.$store.commit('setColor',res.data.data)
② 使用
this.$store.state.color
③Action派发
this.$store.dispatch('login', 'admin').then(() => {
this.$router.push(this.$route.query.redirect)
}).catch(() => {
alert('用户名或密码错误')
})
④模块化
user.js 定义
export default {
namespaced: true, // 避免命名冲突
// ...
}
访问方式响应变化
// Login.vue
<button @click="login" v-if="!$store.state.user.color">登录</button> //多上一个文件名$store.state.user.color和$store.state.color
this.$store.dispatch('user/login', 'admin').then(() => {
const redirect = this.$route.query.redirect || '/'
this.$router.push(redirect)
}).catch(() => {
alert('用户名或密码错误')
})
⑤
import { mapState,mapGetters,mapMutations,mapActions} from 'vuex'
computed:{
...mapState(['color'])
}
methods:{
...mapActions(['setC'])
}
//模块化
...mapState({'name':state=>state.coalgas.token}),
//或者
...mapState('coalgas',['token']),
...mapActions({Login:'coalgas/Login' }),
//或者
...mapActions('coalgas',['Login']),
二 原理
2.1 index.js文件说明
下方文件可以看出vueX是用的new,说明./kvueX.JS文件中是一个构造函数或者类,传入的参数是一个对象。
import Vue from 'vue';
import VueX from './vueX'
Vue.use(VueX);
export default new VueX.store({
state :{
counter :0
},
getters:{
doubleCounter(state){
return state.counter*2
}
},
mutations:{
add (state){
state.counter++
}
},
actions:{
add({commit}){
setTimeout(()=>{
commit('add')
},1000)
}
},
modules:{
}
})
2.2vueX文件说明
首先声明一个全局变量let vue,这是一个插件,在加入vue中都会执行install方法,并且将vue传入。我们用 Vue=_Vue;将前方声明的全局变量赋值为vue。接下来通过混入的方法将所有的组件种豆混入生命周期函数beforeCreate和原有的合并,判断在根实例后将store挂载到Vue的原型属性上。
constructor函数首先对参数进行解析并挂在到原型属性上,通过new Vue的方法将参数中存储数据的参数响应化挂载带实例属性上。将两个函数也挂载到原型属性上。
commit函数,首先第一个参数为用法调用时传入的方法名,第二个参数为用法响应修改的值,通过解析参数拿到用法想要调的方法mutations中的方法,如果方法存在调用方法,传入的第一个参数为响应数据,第二位用法传入的数据。
dispath函数和commit函数基本一样不过在调用actions中的方法时传入的第一个参数为this,也就是vuex对象。
let Vue;
class Store{
constructor(options){
this._mutations=options.mutations;
this._action=options.actions;
this.state=new Vue({
data:options.state
})
this.commit=this.commit.bind(this)
this.dispath=this.dispath.bind(this)
}
commit(type,payload){
const entry=this._mutations[type]
if(entry){
entry(this.state,payload)
}
}
dispath(type,payload){
const entry = this ._action[type]
if(entry){
//此处第一个参数是this,也就是vuex对象,所以在index中使用可以解构 {commit,dispatch,state}
entry(this,payload)
}
}
}
function install(_Vue){
Vue=_Vue;
Vue.mixin({
beforeCreate(){
if(this.$options.Store){
Vue.prototype.$Store=this.$options.store
}
}
})
}
export default{
Store,
install
}