vuex 入门详解

 

在SPA单页面组件的开发中 Vue 的 vuex 和 React 的 Redux 都统称为同一状态管理,个人的理解是全局状态管理更合适;简单的理解就是你在 state 中定义了一个数据之后,你可以在所在项目中的任何一个组件里进行获取、进行修改,并且你的修改可以得到全局的响应变更。下面咱们一步一步地剖析下vuex的使用:

(1)首先要安装、使用 vuex

注意: 在vue 2.0+ 你的vue-cli项目中安装 vuex 

npm install vuex --save

(2)在src文件目录下新建一个名为 store 的文件夹,为方便引入并在 store 文件夹里新建一个index.js,里面的内容如下:

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

Vue.use(Vuex);

// 创建 store 实例
export default new Vuex.Store()

(3)在 main.js里面 引入 store ,然后把 【store 的实例】注入所有的子组件,相当于全局注入,这样一来就可以在任何一个组件里面使用 this.$store 了:

import store from './store'

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

(4)在 store 文件夹下面新建一个 modules 文件夹,然后在modules 文件里面建立需要管理状态的 js 文件,既然要把不同部分的状态分开管理,那就要把它们给分成独立的状态文件了,

import account from './modules/account'

export default new Vuex.Store({
  modules: {
    account,
  }
})

(5)在 store/modules.account.js 中,设置全局访问的 state 对象,要设置初始属性值,通过 db.get 方法获取缓存信息。

state: {
  token: db.get('USER_TOKEN'),
  user: db.get('USER'),
},

(6)通过上面步骤后,你已经可以用 this.$store.state.token 或 this.$store.state.user 在任何一个组件里面获取 token 和 user 定义的值了。

computed: {
  token () {
    return this.$store.state.account.token
  },
  user () {
    return this.$store.state.account.user
  }
},

(7)mutattions也是一个对象,这个对象里面可以放改变 state 的初始值的方法,具体的用法就是给里面的方法传入参数 state 或额外的参数,然后利用 vue 的双向数据驱动进行值的改变,同时 db.save 方法更新缓存信息,如下:

mutations: {
  setToken (state, val) {
    db.save('USER_TOKEN', val)
    state.token = val
  },
  setUser (state, val) {
    db.save('USER', val)
    state.user = val
  },
}

(8)其中的 namespaced:true 表示当你需要在别的文件里面使用( mapGetters、mapActions )时,里面的方法需要注明来自哪一个模块的方法:

import db from 'utils/localstorage'

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

(9)在组件中,如何获取 store 中的多个数据信息呢?当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。mapState 函数返回的是一个对象。通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。

import {mapState} from 'vuex'

computed: {
  // 对象形式
  ...mapState({
    token: state => state.account.token,
    username: state => state.account.user.username,
  }),
  // 数组形式
  ...mapState([
    'token',
    'username'
  ])
},

(10)Getter 接受 state 作为其第一个参数,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

import { mapGetters } from 'vuex'

export default {
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([ 'doneTodosCount', 'anotherGetter' ])
    mapGetters({
      // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
      doneCount: 'doneTodosCount'
    })
  }
}

(11)在组件里面,如何给 store 赋值呢?你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。这里将把登录接口返回的数据存储到 Vuex 和浏览器的 localstorage 中。

import { mapMutations } from 'vuex';

methods: {
  // store.commit 提交 mutation 
  onColorChange (values, colors) {
    this.$store.commit('setting/setColor', colors)
  },
  // mapMutations 映射为 store.commit 调用
  ...mapMutations({
    setToken: 'account/setToken',
    setUser: 'account/setUser',
  }),
  saveLoginData (data) {
    this.setToken(data.token)
    this.setUser(data.user)
  },
}

(12)在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):

import { mapActions } from 'vuex'

export default {
  methods: {
    updateToken() {
      this.$store.dispatch('account/setToken', this.token); // account.js里actions里的setToken方法
    },
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }

登录流程小案例:

(1)登录点击事件:

// 登录操作
async handleSubmit (e) {
  e.preventDefault()
  const result = await this.$store.dispatch('Login', this.form)
},

(2)在 src/store/modules/passport.js 文件里,actions 中,添加接口请求,将结果 userInfo 使用 commit 提交 mutation,数据存储到 Vuex 的 state  中。

const passport = {
  state: {
    info: {},
  },

  mutations: {
    SET_INFO: (state, info) => {
      state.info = info
    },
  }

  actions: {
    // 登陆
    async Login ({ commit }, userInfo) {
      const { username, password } = userInfo
      const resp = await api.login(username, password)
      const { tokenInfo, userInfo } = resp.data
      ...
      commit('SET_INFO', userInfo)
    }
  }
}
export default passport

(3)如何全局获取数据呢?

import { mapState } from 'vuex'

computed: {
  ...mapState: ({
    userInfo: state => state.passport.info
  })
}

mounted () {
  console.log('mounted', this.userInfo)  // 获取到存储在 Vuex 全局的数据状态
}

当然如果我们的登录是弹框的样子,有些路由未登录时,我们会检查登录态,详情请参考:使用 vue-router 全局守卫钩子函数,根据登录状态进行路由拦截以及滚动条回到页面顶部。当判断为未登录状态时,我们需要弹出登录框提示用户登录后,便可以操作。这是我们可以使用 vuex 全局状态管理来控制登录弹框的显示或隐藏。

import { mapMutations } from 'vuex'
methods: {
  ...mapMutations([
    'setLoginVisible',
  ]),
  // 登录点击事件
  toLogin () {
    // 或者使用 this.$store.commit('setLoginVisible', true)
    this.setLoginVisible(true)
  },
}

store 中如何配置呢?

// src/store/modules/user.js
const user = {
  state: {
    loginVisible: false, // 登录弹窗显示
  },
  mutations: {
    setLoginVisible: (state, loginVisible) => {
      state.loginVisible = loginVisible
    },
  }
}
export default user

当然登录组件挂载在主体架构下面的:

// 登录
<login :isShow="loginVisible" v-if="loginVisible" />

export default {
  name: 'Framework',
  components: {
    Login,
  },
  computed: {
    ...mapState({
      loginVisible: state => state.user.loginVisible,
    })
  },
}

那么我们如何设置 Login 组件呢?

// src/views/User/Login/Login.vue
<el-dialog
  title="登录"
  center
  modal-append-to-body
  :visible.sync="isShow"
  :before-close="handleClose"
  :close-on-click-modal="false"
>
  ...
</el-dialog>

登录提交事件:

import { mapActions } from 'vuex'
...mapActions(['Login']),

async handleSubmit (e) {
  e.preventDefault()
  ......
  // 或者使用 await this.$store.dispatch('Login', this.form)
  await this.Login(this.form)
  this.setLoginVisible(false)
}

store 中 action 是异步函数,可以调用接口信息

// src/store/modules/user.js 
import api from '@/http/api/user'
const user = {  
  actions: {
    async Login ({ commit }, userInfo) {
      const { username, password, marketId } = userInfo
      try {
        const resp = await api.login({
          username,
          password,
        })
        const { tokenInfo, userInfo } = resp.data
      } catch (e) {
        throw e
      }
    }
  }
}

当然获取 vuex 中数据状态管理如下:

import { mapState } from 'vuex'
computed: {
  ...mapState({
    userInfo: state => state.user.userInfo || {},
  })
}

// 或者使用 const userInfo = this.$store.state.user.userInfo || {}

为啥我们可以使用 this.$store 来获取存储的全局数据信息呢?

在实例化挂载 Vue 节点时,引入 store 的相关文件信息。

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

总结:

vuex分为state,getter,mutation,action四个模块,四个模块的作用如下:

(1)state:定义变量;

(2)getters:获取变量;

(3)mutations:同步执行对变量进行的操作;

(4)actions:异步执行对变量进行的操作;

(5)mapMutations/mapActions 只是把 mutation/action 函数绑定到methods里面,调里面的方法时正常传参数。

注意:映射都是映射到当前对象,使用时需要用 this 来调用。更多详细信息,请查看 Vuex 官网,参考案例:购物车

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本
Vue.js是一个流行的JavaScript框架,它允许您构建动态Web应用程序。Vuex是一个专为Vue.js应用程序开发的状态管理模式。它允许您在应用程序中管理和维护状态,例如用户信息、购物车、主题等。Vuex将状态存储在一个集中的存储库中,称为store。Vuex的核心概念包括statemutations、actions和getters。 - state:存储应用程序级别的状态,可以通过store.state访问。 - mutations:用于更改状态的函数,必须是同步函数。可以通过store.commit方法调用。 - actions:用于处理异步操作的函数,可以包含任意异步操作。可以通过store.dispatch方法调用。 - getters:用于从store中获取状态的函数,可以通过store.getters访问。 下面是一个简单的示例,演示如何在Vue.js应用程序中使用Vuex: 1.安装Vuex ```shell npm install vuex --save ``` 2.创建store ```javascript import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }, getters: { getCount: state => { return state.count } } }) export default store ``` 3.在Vue组件中使用store ```javascript <template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> <button @click="incrementAsync">Increment Async</button> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { computed: { ...mapGetters([ 'getCount' ]) }, methods: { ...mapActions([ 'increment', 'incrementAsync' ]) } } </script> ``` 在上面的示例中,我们创建了一个名为count的状态,并定义了一个名为increment的mutation和一个名为incrementAsync的action。我们还定义了一个名为getCount的getter,用于从store中获取count状态。在Vue组件中,我们使用mapGetters和mapActions帮助程序将getteraction映射到组件中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值