Write the Code. Change the World.

12月 02

使用 vue,一般都会使用到 vuex(状态管理)和路由(vue router)还有 axios 的。可见 vuex 是多么重要。

vuex 干啥呢。 说到 vuex ,都会带上状态管理。对,就是状态管理。它用来存储响应组件里的状态。我们经常会用到 v-model, 数据变化了,对应的渲染也跟着变化了。可 v-model 是小的玩意,是在当前组件中使用的。vuex 是全局的,对应着整个完整的项目。

想象一下这样的场景。我人在登录页面。使用登录,登录成功,并返回到上一个路由。在返回到上一个路由中,没做任何的数据请求,但是在上一个路由的对应的 ui 界面上,已经显示出了用户的头像昵称这些信息。这是什么鬼,这就是状态管理所带来的影响。

跨组件,跨路由,及时响应。数据驱动渲染。

还有,vuex 中的数据是暂时的。所谓暂时,是指在当前的浏览器里(刷新浏览器就没了),在当前使用的小程序里(小程序手动处理掉进程再进来就没了)。但暂时是能跨越组件和路由噢。上边就已经说过。可及时是暂时的,也是有方法使其长久。

怎么使其长久呢。我们可以使用 cookie,可以使用 localStorage 来搞定。

好了,到此仅仅是文字上说明 vuex 能干啥。下边就落地吧。

vuex 的几个核心概念

Vuex有几个核心概念:State、Getter、Mutation、Action、Module。

  • State:存储状态数据

  • Getter:从状态数据派生数据,相当于State的计算属性。

  • Mutation:存储用于同步更改状态数据的方法,默认传入的参数为state。

  • Action:存储用于异步更改状态数据,但不是直接更改,而是通过触发Mutation方法实现,默认参数为context。

  • Module:Vuex 模块化

它们之间的交互关系如下图。

定义 vuex 的数据结构以及模块划分

我们先定义模块,比如用户模块,订单模块,设置模块等。

在模块中,我们会定义 state,getter, mutation, action 这些。

模块定义好后,我们就可以组织创建 vuex 了。

最后,将 vuex 的实例绑定到 Vue 中。

结构以及对应的 code 如下。

src
└─ store
    ├─ getters.js
    ├─ index.js
    └─ modules
        └─ user.js


# user.js
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'

const getDefaultState = () => {
  return {
    token: getToken(),
    nickname: '',
    avatar: ''
  }
}

const state = getDefaultState()

const mutations = {
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_USER: (state, data) => {
    const fillable = ['nickname', 'avatar']
    for(const key in data) {
      if (fillable.indexOf(key) >= 0) {
        state[key] = data[key]
      }
    }
  },
}

const actions = {
  // user login
  login({ commit }, userInfo) {
    const { account, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ account: account.trim(), password: password }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data.token)
        setToken(data.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          return reject('请登录')
        }

        commit('SET_USER', data)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // user logout
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // must remove  token  first
        resetRouter()
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      removeToken() // must remove  token  first
      commit('RESET_STATE')
      resolve()
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

# getters.js
const getters = {
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  nickname: state => state.user.nickname
}
export default getters

# index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import user from './modules/user'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    user
  },
  getters
})

export default store

再在 main.js 中注入绑定一下。

# main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import router from './router'

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

到此,状态管理已经构造成功了。那么怎么使用呢。

使用 vuex

  • 使用辅助函数来处理。
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'

在计算属性 computed 中注入 state 和 getters 。如:

<template>
  <div class="home-container">
      <div>{{ nickname }}</div>
      <div>{{ avatar }}</div>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState({
      nickname: state => state.user.nickname,
    }),
    ...mapGetters(['avatar'])
  },
  mounted() {
  }
}
</script>

或干脆使用模块名。如:

  computed: {
    ...mapState('user', ['nickname']),
    ...mapGetters('user', ['avatar'])
  },

想要体验到初始化效果,可以初始化给 state 默认值。如:

# src/store/modules/user.js

const getDefaultState = () => {
  return {
    token: getToken(),
    nickname: '我是一只游泳的鱼',
    avatar: 'fish.jpg'
  }
}

在 methods 中注入 mutations 和 actions 。如:

  methods: {
    ...mapMutations('user', [
      // 将 `this.SET_USER()` 映射为 `this.$store.user.commit('SET_USER')`
      'SET_USER'
    ]),
    ...mapActions('user', [
      // 将 `this.login()` 映射为 `this.$store.user.dispatch('login')`
      'login'
    ]),
 }

这个就是数据庞大后,数据分类所处理的情况。如果不适用 module,就相当于单个的 module 了。

上边这里使用的都是钩子的方式。不适用钩子也可以的。

this.$store.user.dispatch('login')

this.$store.user.commit('SET_USER')

this.$store.user.state.nickname

记住,我们不能直接去给 state 进行赋值。

文章来源

https://www.cnblogs.com/fengyuexuan/p/10946073.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注