Vuex 需要掌握的基础用法

简介: Vuex是专为Vue.js开发的状态管理模式,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态可预测的方式发生变化

Vuex是专为Vue.js开发的状态管理模式,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态可预测的方式发生变化

  • 安装
vue add vuex

基础使用

  • State
    将应用全局状态定义在state中

    // store/index.js
    export default new Vuex.Store({
      state: {
        isLogin: false,
      }
    });
  • Mutation
    修改state只能通过mutation

    export default new Vuex.Store({
      // ...
      mutations: {
        login(state) {
          state.isLogin = true;
        },
        logout(state) {
          state.isLogin = false;
        },
      }
    });
  • 获取和修改状态
    使用$store.state获取属性

    <button @click="login" v-if="!$store.state.isLogin">Login</button>
    <button @click="logout" v-else>Logout</button>

    修改状态只能通过store.dispatch(mutation)

    this.$store.commit('login');
    this.$store.commit('logout');
  • Action
    Action类似于mutation,但是

    • Action提交的是mutation,而不是直接变更状态
    • Action可以包含任意异步操作

      // store/index.js
      actions: {
        // 参数1 是vuex传递的上下文context
        login({ commit }, username) {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              if (username === 'admin') {
                commit('login');
                resolve();
              } else {
                reject();
              }
            }, 1000);
          });
        },
      }

    派发动作

    this.$store.dispatch('login', 'admin').then(() => {
      // 业务逻辑
    })

模块化

使用modules定义多个子模块利于组件复杂状态

import user from './user'
export default new Vuex.Store({
  modules: {
    user,
  }
})

在子模块中维护状态

export default {
  namespaced: true, // 避免命名冲突
  // 状态及维护逻辑
}

访问方式加上命名空间

this.$store.dispatch('user/login', 'admin').then(() => {})

this.$store.commit('user/logout');

// store.state.user.isLogin

mapState()/mapMutation()/mapAction()

通过这些方法,可以简化访问方式

import { mapState } from 'vuex';
export default {
  // 展开后可直接访问 isLogin
  computed: {
    ...mapState('user', ['isLogin']),
  }
}

维护

import { mapActions } from 'vuex';
export default {
  methods: {
    login() {
      this.['user/login']('admin').then(() => {})
    },
    ...mapActions(['user/login', 'user/logout']),
  }
}

Getter

可以用getters从store的state中派生出一些状态,类似于计算属性

export default {
  namespaced: true, // 设置独立命名空间,避免命名冲突
  state: {
    isLogin: false,
    username: '',
  },
  getters: {
    welcome: (state) => `${state.username},欢迎回来`,
  },
}

严格模式

严格模式下,强制要求状态变更必须由mutation维护

export default new Vuex.Store({
  strict: true,
})

插件

Vuex 的 store 接受plugins选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数

const myPlugin = (store) => {
  // 当 store 初始化后调用
};

插件注册

const store = new Vuex.Store({
  // ...
  plugins: [myPlugin],
});

简易实现

Vuex 集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化。

需求分析

  • 实现一个插件:声明Store类,挂载$store
  • Store具体实现

    • 创建响应式的state,保存mutations,actions和getters
    • 实现commit根据用户传入type执行对应mutation
    • 实现dispatch根据用户传入type执行对应action,同时传递上下文
    • 实现getters,按照getters定义对state做派生

实现

  1. 实现一个插件
// cvuex.js
let Vue;
class Store {
  constructor(options) {
    // 响应化处理state
    this.state = new Vue({
      data: options.state,
    })
  }
}
function install(_Vue) {
  Vue = _Vue;
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store;
      }
    }
  })
}
// cvuex
export default {
  Store,
  install,
}
  1. 实现commit
// cvuex.js
class Store {
  constructor(options) {
    this._mutations = options.mutations;
    // 响应化处理state
    this.state = new Vue({
      data: options.state,
    })
  }
  // store.commit('add', 1)
  /**
   * @type mutation的类型
   * @payload 参数
   */
  commit(type, payload) {
    const entry = this._mutations[type];
    if (entry) {
      entry(this.state, payload);
    }
  }
}
  1. 实现dispatch
// cvuex.js
class Store {
  constructor(options) {
    this._mutations = options.mutations;
    this._actions = options.actions;
    // 响应化处理state
    this.state = new Vue({
      data: options.state,
    })
    // 绑定commit、dispatch的上下文为store实例
    this.commit = this.commit.bind(this);
    this.dispatch = this.dispatch.bind(this);
  }
  commit(type, payload) {
    const entry = this._mutations[type];
    if (entry) {
      entry(this.state, payload);
    }
  }
  dispatch(type, payload) {
    const entry = this._actions[type];
    if (entry) {
      entry(this, payload);
    }
  }
}
  1. 实现getters
class Store {
  constructor(options) {
    // ...
    this._wrappedGetters = options.getters;

    const computed = {};
    this.getters = {};
    const store = this;
    Object.keys(this._wrappedGetters).forEach(key => {
      // 获取用户定义的getter
      const fn = store._wrappedGetters[key];
      // 转换为computed可以使用的无参数形式
      computed[key] = function() {
        return fn(store.state);
      }
      // 为getters定义只读属性
      Object.defineProperty(store.getters, key, {
        get: () => store._vm[key]
      });
    })
    this._vm = new Vue({
      data: {
        // 加两个$$ vue创建的时候不会做代理,对外隐藏
        $$state: options.state,
      },
      computed
    });
  }
  // ...
}
相关文章
|
2月前
|
缓存 JavaScript
vuex的讲解与相关用法
vuex的讲解与相关用法
10 0
|
5月前
|
存储 资源调度 JavaScript
vuex详细用法
vuex详细用法
25 0
|
5月前
|
存储 资源调度 JavaScript
vuex是什么?如何使用?使用他的功能场景?
vuex是什么?如何使用?使用他的功能场景?
25 0
|
5月前
vant-函数式组件用法
vant-函数式组件用法
47 0
|
6月前
|
设计模式 JavaScript 前端开发
【Vue】模块基本语法「上篇」
【Vue】模块基本语法「上篇」
24 0
|
8月前
|
资源调度 JavaScript
vuex如何使用
Vuex是一个专为Vue.js设计的状态管理模式。它集中式管理了应用中所有组件的状态,使得状态管理更加简单和高效。下面是使用Vuex的基本步骤:
36 0
|
9月前
|
监控 JavaScript 前端开发
vuex和redus的异同
vuex和redus的异同
|
10月前
|
JavaScript
Vue —— 进阶 Vuex(一)(四个 map 的用法、模块化和命名空间)
Vue —— 进阶 Vuex(一)(四个 map 的用法、模块化和命名空间)
244 0
|
10月前
|
存储 JavaScript 数据管理
Vue —— 进阶 Vuex(零)(概念、工作原理、环境搭建、基本使用、getters)
Vue —— 进阶 Vuex(零)(概念、工作原理、环境搭建、基本使用、getters)