vuex 快速上手与原理浅析

198 阅读1分钟

vuex 快速上手与原理浅析

概念

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (数据)

作用

将路由,组件等内部散乱的状态(数据)统一管理,方便在合适的场景被使用。

优势

相对于全局变量存储有何优势?

  1. 响应式

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  1. 可跟踪

你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

使用

通过一个行程列表展示,查看行程详情的例子了解 vuex 的具用法。

安装

推荐

npm install vuex --save

其他方法

vue 引入 vuex

// main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

状态,方法定义

// store.js

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
let store = new Vuex.Store({
    state: {
        orders: [],
        curOrder: {
            start: "",
            end: ""
        }
    },
    getters: {
    },
    mutations: {
        setOrderList(state, data) {
            state.orders = data
        },
        setCurOrder(state, data) {
            state.curOrder = data
        }
    },
    actions: {
        async getList({
            commit
        }, params) {
            let data = await axios.get("path/orders", {
                params
            })
            commit('setOrderList', data)
        }
    }
});
export default store

vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态,每个应用将仅仅包含一个 store 实例,简单理解就是上面的 store.js

  • state

用于定义和存储状态,例如 orders 存放行程列表,curOrder 存放当前选中的行程。

  • mutations

更改 state 的唯一方法是提交 mutation,例如 setOrderList,修改 行程列表数据。

  • actions

Action 类似于 mutation,但是不能直接修改状态,需要通过 mutations 间接修改,Action 可以包含任意异步操作。

应用使用 vuex

// list.vue

<template>
  <div @click="goDetail(item)" v-for="item in list">
    <div>起点:{{item.start}}</div>
    <div>终点:{{item.end}}</div>
  </div>
</template>
<script>
import { mapMutations, mapActions, mapState } from "vuex"

export default {
  data() {
    return {
    }
  },
  computed: {
    ...mapState([
      "list"
    ])
  },
  methods: {
    ...mapMutations(["setCurOrder"]),
    ...mapActions(["getList"]),
    goDetail(item) {
      this.setCurOrder(item);
      // to detail 页面
    }
  },
  created() {
    this.getList();
  }
}
</script>

  • mapState state 辅助函数

mapState 函数返回的是一个对象,使用对象展开运算符,将 state 合并到当前组件的 computed 中,使用 state 就像使用 computed 一样容易。

  • mapActions actions 辅助函数

mapActions 函数将 vuex 中定义的 actions 引入到当前组件 methods 中,需要获取数据时像调用普通方法一样,由于 getList 已经自动将获取的数据 orders 通过 setOrderList 存储到 state 中,所以在页面中可以直接使用 orders。

  • mapMutations mutations 辅助函数

mapMutations 将 vuex 中定义的 mutations 引入到 methods 中,当前点击需要查看详情的行程时,通过 setCurOrder 将选中行程放入 curOrder 中。

// detail.vue

<template>
  <div>
    <div>起点:{{curOrder.start}}</div>
    <div>终点:{{curOrder.end}}</div>
  </div>
</template>
<script>
import { mapGetters, mapActions, mapState } from "vuex"
export default {
  data() {
    return {
    }
  },
  computed: {
    ...mapState([
      'curOrder'
    ])
  }
}
</script>

当通过路由跳转到 detail 详情页时,通过 curOrder 直接获取列表页中已经存储的数据。

原理解析

vuex 流转图

Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components,界面随之更新

vue 装载 vuex

vue.use(vuex)

const install= (_vue)=>{
    Vue = _vue
    Vue.mixin({ beforeCreate() {
        if(this.$options.store){
            Vue.prototype.$store = this.$options.store
        }
    } })
}

执行 vue.use 会调用 vuex 的 install 方法,使用 vue 实例可以方便使用 this.$store 调用 vuex 的 api

vuex 中 state 定义

  constructor(options){
        this._vm = new Vue({
            data:{
                $$state:options.state,
            }
        });
        this._committing = false;
          this._actions = options.actions;
        this.commit = this.commit.bind(this);
        this.dispatch = this.dispatch.bind(this);
    }

通过 vue 的 data 将 state 数据赋予响应式

commit 方法

commit(type,payload){
        const entry = this._mutations[type]
        if(entry){
            entry(this.state,payload)
        }
    }

commit 方法传入 mutations 中已经定义的 type 值调用对应的方法并传入指定的参数

dispatch 方法

dispatch(type,payload){
        const entry = this._actions[type]
        if(entry){
            entry(this.state,payload)
        }
    }

dispatch 方法传入 actions 中已经定义的 type 值调用对应的方法并传入指定的参数

控制 state 不被恶意使用

    get state(){
        return this._vm._data.$$state;
    }
    set state(v){
        if(!this._committing){
            console.error("不能直接使用",v)
        }        
    }

state 只能被获取无法被外界赋值,只能通过 mutations 修改。

总结

这就是 vuex 的基本使用和原理浅析。

文中未讲到的内容例如 Module,后续补充敬请留意。

文献参考

vuex.vuejs.org/zh/guide/ github.com/s249359986/…