17.vuex

vuex作用

多个页面都需要用到的数据,你可以使用vuex来存储。

 

如何使用?

首先需要安装vuex

cnpm i vuex

然后在项目的src目录下创建一个store的文件夹,接着创建一个number.js,该文件用于存储数字。这个数字各个页面都需要用到。然后编写以下代码 :

const state = {
    number : 100
};

export default{
    state
}

vuex规定,公共的数据用一个变量名叫state的对象存储,需要注意的是这个变量的名字不能改成别的。

然后在store文件夹下创建一个index.js,编写以下代码 :

import Vue from 'vue'
import Vuex from 'vuex';
import NumberManager from './number';

Vue.use(Vuex);

export default new Vuex.Store(NumberManager);

最后把vuex注入到vue中即可。打开main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store' //这里!!!

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store, //这里!!!
  components: { App },
  template: '<App/>'
})

准备工作都完成了,现在你可以在各个页面中,使用

this.$store.state.变量名

来访问公共数据。比如我想在某个页面中访问number,则 :

this.$store.state.number

 

mutations

vuex除了可以读取公共数据外,当然也可以设置公共数据。比如上面的例子,我想把number的值改成101,则需要用到一个叫"mutations "的东东。如 :

const state = {
    number : 100
};

const mutations = {
    setNumber(state,number){
        state.number = number; 
    }
}

export default{
    state,
    mutations //注意这里需要导出
}

mutations下的setNumber是函数名,随便一个名字都可以。函数有2个参数,第一个参数是state对象,就是我们上面定义的

const state = {
    number : 100
};

第二个参数是一个值,用来修改number。然后我们就可以使用vuex提供的commit方法来修改number的值了。如下 :

this.$store.commit('setNumber',101);

commit的第一个参数是mutations下定义的函数名,第二个是修改的值。

说到这里,或许你会问为什么我们都可以以

this.$store.state.number

这样的方式来访问到number的值了,我们直接修改不可以吗?比如这样 :

this.$store.state.number = 101;

直接修改确实可以,但是不推荐这样做,后面会说这个原因。

 

getter

访问vuex中的某个变量,我们都需要写一大串this.$store.state.xxx,此时使用getter可以简化这不操作。在number.js中增加以下代码 :

const state = {
    number : 100
};

const getters = {
  getNumber : (state)=>{
      return state.number;
  }
}

const mutations = {
    setNumber(state,number){
        state.number = number; 
    }
}

export default{
    state,
    getters, //注意导出
    mutations
}

然后在使用的组件页面上,需要引入mapGetters,如下 :

import { mapGetters } from 'vuex';

然后在computed下定义函数名

computed : {
  ...mapGetters([

    'getNumber ',

  ])
}

这样我们就可以直接访问通过getNumber来访问number的值了。如下 :

<template>
  <div class="hello">
    {{getNumber}} //直接访问vuex中,number的值
  </div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
  computed : {
    ...mapGetters([
      'getNumber ',
    ])
  },
  created(){
    console.log(this.getNumber); //直接访问vuex中,number的值
  }
}
</script>
<style scoped>
</style>

 

actions

vuex里,除了state、getters、mutations,还提供了一个叫actions的东西。它是用来执行异步操作的,但最后也是修改state里的数据。

例子 :

比如现在公共数据里,我想把用户的登录信息也保存在vuex中,用户信息需要请求某个接口来获取,这个请求的代码就可以放在actions中。

先在number.js中增加以下代码 :

const state = {
    number : 100,
    userMsg : '',
};

const getters = {
    getNumber : (state)=>{
	    return state.number;
  }
}

const actions = {  //新增
   getUserMsg({commit}){
        let str = {
            name : 'tom',
            level : 'vip8'
        }
        commit('setUserMsg', str);
    }
}

const mutations = {
    setNumber(state,number){
        state.number = number; 
    },
    setUserMsg(state,str){ //新增
        state.userMsg = str; 
    } 
}

export default{
    state,
    getters,
    actions, //注意导出
    mutations
}

actions里的变量str,这里由于没有接口,我们暂时把str的值当做是请求某个接口得来的。正常的写法大概是这样的 :

const actions = {
   async getUserMsg({commit}){
        let str = '';
        let res = await axios({
            method: 'post',
            url: '/api/getUserMsg',
            data: {
                type : 'getUserMsg',
            }});
        if(res.returnCode == 200){
            str = res.data.userMsg;
            commit('setUserMsg', str);
        }
    }
}

然后如果在某个页面中,我们需要获得用户的信息,我们可以执行以下代码 :

this.$store.dispatch('getUserMsg');

执行这句后,vue会去检查vuex里的actions有没有getUserMsg这个方法,有的话就会执行,最后还是调用commit,执行mutations里的方法,把用户信息保存在state里。

 

models

上面的actions例子中,我们在state的变量里,存放了一个叫userMsg的变量,但仔细想想,这个number.js只是用来存储数字的,这时候把用户信息存储在number.js里,是否不太合适?此时我们可以使用vuex提供的models属性。具体步骤如下 :

1、把number.js里,userMsg的相关数据提取出来,再写一个js脚本。如下 :

user.js

const state = {
    userMsg : '',
};

const actions = {
   getUserMsg({commit}){
        let str = {
            name : 'tom',
            level : 'vip8'
        }
        commit('setUserMsg', str);
    }
}

const mutations = {
    setUserMsg(state,str){
        state.userMsg = str; 
    } 
}

export default{
    state,
    actions,
    mutations
}

写法和number.js一模一样。

2、修改store文件夹下的index.js

import Vue from 'vue'
import Vuex from 'vuex';
import NumberManager from './number';
import UserManger from './user';

Vue.use(Vuex);

export default new Vuex.Store({
    modules : {
        NumberManager,
        UserManger
    }
});

这样既可。

需要注意的是,如果使用了modules,此时我们访问vuex中的这个number,就不能这样写了

this.$store.state.number

因为此时的state有2个,一个是number.js的,一个是user.js的,正确的写法如下 :

this.$store.state.NumberManager.number

NumberManager是在index.js里import时,定义的名字。这样写代码貌似更长了,所以我们可以使用上面说到的,使用getters来获取vuex中的变量

 

plugins

现在我们把number的值改成101,但是如果此时把

this.$store.commit('setNumber',101);

这段代码注释掉,在刷新浏览器发现,number的值还是100。此时我们可以使用vuex提供的plugins插件功能。步骤如下 :

1、新建一个js,名字随意。这里我取名叫saveInLocal.js,然后在这个js里编写以下代码 :

export default store => {
    if (localStorage.state) {
        store.replaceState(JSON.parse(localStorage.state));
    }
    store.subscribe((mutation, state) => {
      localStorage.state = JSON.stringify(state);
    })
  }

如果看不懂es6的写法,可以参考下面的代码,功能是一样的

export default function(store){
    if (localStorage.state){
      store.replaceState(JSON.parse(localStorage.state));
    } 
    store.subscribe(function(mutation, state) {
        localStorage.state = JSON.stringify(state);
    });
  }

2、修改index.js

import Vue from 'vue'
import Vuex from 'vuex';
import NumberManager from './number';
import UserManger from './user';
import saveInLocal  from './saveInLocal '; //这里!!!

Vue.use(Vuex);

export default new Vuex.Store({
    modules : {
        NumberManager,
        UserManger
    },
    plugins : [saveInLocal] //这里!!!
});

好了,此时只要修改vuex中的数据,再刷新浏览器数据还是没有丢失。原因是我们配置了plugins。只要配置了这个插件,那项目

运行的第一次就会去执行plugins规定好的函数。该函数只有一个返回值,那就是store。这里的store和我们在页面内,

使用的this.$store是同一个东西。

先来分析下这几句代码 :

if (localStorage.state){
   store.replaceState(JSON.parse(localStorage.state));
} 

localStorage.state是一个自定义属性,localStorage的自定义属性都会保存在浏览器中,比如 :

然后在来看下面这句代码 :

store.subscribe(function(mutation, state) {
    localStorage.state = JSON.stringify(state);
});

这句代码相当于一个注册监听函数,当我们使用this.$store.commit来修改vuex中的数据时,修改完毕后会调用subscribe这个方法, 该方法返回的state就是vuex中所有的state。比如我们例子中的number.js和user.js中的state

然后我们把它转换成字符串,存储在localStorage.state中。所以一开始的这句代码

if (localStorage.state){
   store.replaceState(JSON.parse(localStorage.state));
} 

就是判断localStorage.state有没有值,如果有则取出来转换成json格式,并且调用store的replaceState方法覆盖所有state。这也

是为什么我们不要直接修改state的值的原因

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值