vue中使用store以及modules,并解决当刷新浏览器后,值就被重置的问题

一、store的基本使用

1、首先配饰store,当创建好vue项目后,会自动创建一个store目录,如下图所示:

2、而在main.ts中会自动将该store应用到vue中,如下图所示:

3、此时就可以在其他vue文件中使用this.$store.来访问store中的内容了,那么现在定义store,代码如下:

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

Vue.use(Vuex)
const moduleA = {
  state: () => (
    {msg: 'moduleA'}
  ),
  mutations: {
    INIT1(state, newState) {
      state.msg = 'moduleA:' + newState.msg;
    }
  },
  actions: { 
    init1 (context, newState) {
      context.commit('INIT1', newState)
    }
  }
}
export default new Vuex.Store({
  state: {//state中是用于定义变量的,相当于java中的int定义一个变量的功能
    msg:'init'
  },
  // 创建改变状态的方法
  mutations: {//是定义方法的结构,在外部可以通过this.$store.commit('INIT', state);来调用INIT函数,然后更新state结构中定义的变量值
    INIT (state, newState) { //state是本store中的状态,newState传commit中第二个参数
      state.msg = newState.msg;
    }
  },
  // 创建驱动actions可以使得mutations得以启动
  actions: {//触发状态更新,当需要更新多个状态的时候使用,如this.$store.dispatch('login', state);
    init (context, newState) {
      context.commit('INIT', newState)//相当于调用了mutations中的INIT方法
    }
  },
  modules: {
    a: moduleA//注意:当通过this.$store.commit('INIT)发送数据时,如果模块a中也有INIT,那么它会广播到模块A中
  }
})

4、在vue中使用,如:

<template>
  <div>
    <p class="col-md-6">
      <button class="btn btn-primary" @click="setStoreCommit">设置store(commit)</button>
    </p>
    <p class="col-md-6">
      <button class="btn btn-primary" @click="setStoreDispatch">设置store(dispatch)</button>
    </p>
    <p class="col-md-6">
      <button class="btn btn-primary" @click="getStore">获取store</button>
    </p>
  </div>
</template>
<style scoped lang="less">
</style>
<script>
export default {
  methods: {
    setStoreCommit() {
      let state = {msg:'setStoreCommit'};
      this.$store.commit('INIT', state);//调用了非模块中的mutations中的INIT方法
      this.$store.commit('INIT1', state);//调用了模块A中的mutations中的INIT1方法
    },
    setStoreDispatch() {
      let parm = {msg:'Dispatch'}
      this.$store.dispatch('init', parm);//调用了非模块中的actions中的init方法
      this.$store.dispatch('init1', parm);//调用了模块a中的actions中的init1方法
    },
    getStore() {
      console.log(this.$store.state.msg, this.$store.state.a.msg)//获取状态变量值
    }
  }   
}
</script>

5、然后在另外的界面上有一个获取按钮,如:

<template>
  <div>
      <p class="col-md-6">
        <button class="btn btn-primary" @click="getStore">获取store</button>
      </p>
  </div>
</template>
<style lang="less">
</style>
<script>
export default {
  mounted: function() {
  },
  methods: {
    getStore() {
      console.log(this.$store.state.msg, this.$store.state.a.msg)
    }
  }
}
</script>

6、第一个界面

第二个界面

7、首先点击获取store按钮,输出结果如下图所示:

8、然后点击设置store(commit)按钮,然后再点击获取,输出结果如下图所示:

接着点击设置store(dispatch),在此点击获取,如下图所示:

9、然后跳转到另外一个页面,注意:是跳转,不是直接在url中输入地址,然后再次获取,如下图所示:

由此可见只要是不刷新浏览器,那么设置的值就是全局的

二、解决当刷新浏览器后,值不改变

1、产生的原因为:因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值。

2、解决思路:

一种是state里的数据全部是通过请求来触发action或mutation来改变
一种是将state里的数据保存一份到本地存储(localStorage、sessionStorage、cookie)中
很显然,第一种方案基本不可行,除非项目很小或者vuex存储的数据很少。而第二种可以保证刷新页面数据不丢失且易于读取。

3、解决过程:首先得选择合适的客户端存储,localStorage是永久存储在本地,除非你主动去删除;sessionStorage是存储到当前页面关闭为止;cookie则根据你设置的有效时间来存储,但缺点是不能储存大数据且不易读取。
我选择的是sessionStorage,选择的原因vue是单页面应用,操作都是在一个页面跳转路由,另一个原因是sessionStorage可以保证打开页面时sessionStorage的数据为空,而如果是localStorage则会读取上一次打开页面的数据。
4、用sessionStorage来保存state里的数据。
第一种方案
由于state里的数据是响应式,所以sessionStorage存储也要跟随变化。又由于vuex规定所有state里数据必须通过mutation方法来修改,所以第一种方案就是mutation修改state的同时修改sessionStorage对应存储的属性
第二种方案
第一种方案确实可以解决问题,但这种方法很明显让人觉得怪异,都这样了,那不如直接用sessionStorage来做状态管理。
那怎么才能不用每次修改state时同时也要修改sessionStorage呢?这时我们可以换一个思路,因为我们是只有在刷新页面时才会丢失state里的数据,那有没有办法在点击页面刷新时先将state数据保存到sessionStorage,然后才真正刷新页面?
当然有,beforeunload这个事件在页面刷新时先触发的。那这个事件应该在哪里触发呢?我们总不能每个页面都监听这个事件,所以我选择放在app.vue这个入口组件中,这样就可以保证每次刷新页面都可以触发。

5、在main.ts中实例化vue时加入代码如下图所示:

代码如下:

  created() {
    //在页面加载时读取sessionStorage里的状态信息
    if (sessionStorage.getItem("store")) {
      console.log('页面重新加载');
      let storet = sessionStorage.getItem("store");
      this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(storet == null ? '' : storet)))
    }
    //在页面刷新时将vuex里的信息保存到sessionStorage里
    window.addEventListener("beforeunload", () => {
      console.log('页面被刷新');
      let state = JSON.stringify(this.$store.state)
      sessionStorage.setItem("store", state == null ? '' : state)
    })
  }

6、此时在重新刷新页面后获取store即可,如下输出结果:

7、注意:如果此时在浏览器中另外打开一个选项卡,那么此时又会是新的实例。

参考:https://blog.csdn.net/guzhao593/article/details/81435342

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值