vuex实现数据持久化

vuex-状态管理工具

对于vuex来说,它只是一个状态管理工具,当有些变量不止在组件间用时,可能很多页面都会复用。我们使用vuex进行管理。

state:设置初始值状态。

getters:store仓库的计算属性,主要作用是派生出一些新的状态。比如将state状态的数据进行一次映射或者筛选。

mutations:对state数据进行赋值操作,并进行相应操作;利用store.commit()触发该操作,

actions处理异步操作,可以使用commit方法,使用store.dispatch()触发。

实现数据的持久化--跟localStorage结合使用

设置state的状态:

const state = {
    status: '0'
};

设置getters:

    getStatus(state) {
        let t = localStorage.getItem('isLogined')
        if (t == null || t== undefined) {
            t = state.isLogined;
        }
        state.isLogined=t;
        return state.isLogined;
    }    

设置mutations:

SET_STATE(state, val) {
        state.status = val;
        try {
            localStorage.setItem('isLogined',val);
        } catch (e) {
            console.log(e);
        }
    }

使用-----在页面的计算属性 根据getter获取状态

 

computed:{
      isLogined(){
        return this.$store.getters['getStatus'];
    }   
}        

 操作----修改状态即在方法中调用commit:

methods:{
  handleStatus(){
     this.$store.commit('SET_STATUS','1');        
  }
}

(小知识点:如果是在公共函数内调用,请引入store的index的js文件,调用store.getters和store.commit)

storage的存储方式:

localStorage的存储是按照字符串存储的(以上例子为存储字符串格式)。如果存储为对象格式,会出现返回值是{Object object}的情况,那么,存储时要将数据转成string格式,请使用如下方式:

   localStorage.setItem('obj',JSON.stringfy(object));

storage的读取和使用:

   JSON.parse(localStorage.getItem('obj'));

注意点:

getter的值是要根据依赖值进行变化的, 即如果return的返回值不是state的数据,则监听不到数据变化。

假如只是return localStorage.getItem('status')的话, 则数据不会更新。必须进行state的赋值和return操作。

如果不需要对数据二次改造的话,也可以写到state的初始值: status: localStorage.getItem('isLogined') || '0'。这样的话取数据只能用this.$store.state.status来获取了。

---同理,computed的计算属性也应该和data的数据依赖。

 

插播一点: 可使用node require引入文件的方式  遍历模板,避免模板过多,每次引入文件。

 

const modulesFiles = require.context('./modules', false, /\.js$/);
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'  $1是正则里边的捕获,(.*)内的内容;
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1');
  const value = modulesFiles(modulePath);
  modules[moduleName] = value.default;
  return modules;
}, {});

const store = new Vuex.Store({
  modules,
});

 

  

---------------------------------------------------------------想看原理的请继续往下划👇,如何使用👆------------------------------------------------------------------------------------------------------------

实现原理

1、vuex本质是一个对象,有两个属性:install方法和Store类。

2、install方法的作用是将store这个实例挂载到所有组件。

3、Store这个类有commit,dispatch方法,store类将用户传入的数据包装成data,作为new Vue的参数,从而实现state的响应式。

  • 剖析vuex本质

 

Vue项目中是怎么引入Vuex?

 

  1. 安装Vuex,再通过import Vuex from 'vuex'引入
  2. 先 var store = new Vuex.Store({...}),再把store作为参数的一个属性值,new Vue({store})
  3. 通过Vue.use(Vuex) 使得每个组件都可以拥有store实例

使用Vue.use(), 而 Vue.use的使用原则是执行对象的install方法。 如果参数是对象,则执行对象的install方法,如果是函数,则将函数当成install执行。

class store{

}

function install (){

}

export default {store, install}

1、插件的类型,可以是install方法,也可以是一个包含install方法的对象。

2、插件只能被安装一次,保证插件列表中不能有重复的插件。

实现:

Vue.use = function(plugin){
 const installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
 if(installedPlugins.indexOf(plugin)>-1){
  return this;
 }
 <!-- 其他参数 -->
 const args = toArray(arguments,1);
 args.unshift(this);
 if(typeof plugin.install === 'function'){
  plugin.install.apply(plugin,args);
 }else if(typeof plugin === 'function'){
  plugin.apply(null,plugin,args);
 }
 installedPlugins.push(plugin);
 return this;
}

注意点: 首先要判断插件是不是已经注册过,如果注册过,则直接终止方法。保证相同插件不会被重复加载。

通过Vue.use(Vuex) 使得每个组件都可以拥有store实例:

function install() {
  Vue.mixin({
    beforeCreate() {
      if (this.$options && this.$options.store) { //根组件,传入vue的参数,可通过$options.store访问。
        this.$store = this.$options.store;
      } else { //不是根组件 
        this.$store = this.$parent && this.$parent.store;
      }
    },
  });
}

mixin的作用是将mixin的内容混合到Vue的初始化options中。为什么是beforeCreate 中执行? 因为created中,$options已经初始化好了。

现在实现类store

let Vue
//myVuex.js
class Store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            }
        })

        let getters = options.getter || {}
        this.getters = {}
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, {
                get: () => {
                    return getters[getterName](this.state)
                }
            })
        })

        let mutations = options.mutations || {}
        this.mutations = {}
        Object.keys(mutations).forEach(mutationName => {
            this.mutations[mutationName] = (arg) => {
                mutations[mutationName](this.state, arg)
            }
        })

        let actions = options.actions
        this.actions = {}
        Object.keys(actions).forEach(actionName => {
            this.actions[actionName] = (arg) => {
                actions[actionName](this, arg)
            }
        })

    }
    //dispatch,commit是方法;其余getter,state是属性!!!
    dispatch(method, arg) {
        this.actions[method](arg)
    }
    commit = (method, arg) => {
        console.log(method);
        console.log(this.mutations);
        this.mutations[method](arg)
    }
    get state() {
        return this.vm.state
    }
}
let install = function (vue) {
    ×××省略
}

let Vuex = {
    Store,
    install
}

export default Vuex

 

生命周期执行顺序:

data和el什么时候有数据:

 

 

参考文章:

https://zhuanlan.zhihu.com/p/166087818

 

posted @ 2022-01-05 16:30  阿兰儿  阅读(1132)  评论(0编辑  收藏  举报