快速掌握vuex核心属性使用方法

文章发布于 2023-07-08

什么是vuex

vuex是专为vue开发的一个状态管理库。它集中存储管理应用所有组件的状态。

你可以在应用内的任意一个组件中获取、修改vuex里的状态,一处修改,全局更新状态。再也不用往子孙组件一层一层传递数据了,是不是感觉很痛快。接下来带你们快速掌握vuex

安装vuex

//npm 
npm install vuex --save

//yarn
yarn add vuex --save

--save 会记录到package.json 的dependencies 中,代表项目需要的意思,不论生产环境还是开发环境,项目都会使用。默认就是--save ,在命令行中也可以不写。

开始

了解store

store 仓库,容器的意思。一个项目的所有状态都存在store中。vuex提供了获取、修改仓库状态的办法,我会在文章下面列出两个办法。现在不着急,我们接着了解vuex的几个核心概念。

state

单一状态树,存放状态的对象。

获取state

this.$store.state.user

辅助函数mapState

在一个组件中,如果要使用多个状态,可以使用mapState将state声明计算属性。然后使用计算属性的值

computed:mapState({
    user: user => state.user,
    sex_text: sex => state.sex==1?'男':(state.sex==2?'女':'—'),
    sex: sex => state.sex
})

上面通过计算属性将性别转换成男或女。

通过拓展符号来实现

computed:{
    geN(){}, //组件的其他计算属性
    ...mapState({
        user: user => state.user,
        sex_text: sex => state.sex==1?'男':(state.sex==2?'女':'—'),
        sex: sex => state.sex
    })
}

在组件中使用

<div>{{sex_text}}</div>

初始化state

state:{
    user:'admin',
    nickName:'',
    sex:1, //12 女
}
getter

派生state状态,就是对state的状态进行二次处理,返回处理之后的状态。

下面例子中,getter 筛选state状态树中的列表。

const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
      // 将todos列表中done为true的全部筛选出来
    doneTodos (state) {
      return state.todos.filter(todo => todo.done)
    },
    //查找todos为中id对应的对象
    getId:(state)=>(id) => {
        return state.todos.find(todo=>todo.id === id)
    }
  }
})

辅助函数mapGetters

将store中的getter映射到当前组件中。

// 获取getter的派生状态
computed:mapGetters([
    'doneTodos'
])

// 给派生状态起别名
computed:mapGetters({
    doneTodosCount: 'doneTodos'
})

// 扩展符,不影响组件自身使用计算属性
computed:{
    ...mapGetters({
        doneTodosCount: 'doneTodos'
    })
}

模板中使用

<template>
    <ul>
        <li v-for="(item,index) in doneTodosCount" :key="index">{{item.text}}</li>
    </ul>
</template>
mutations

更改state状态 ,提交mutations的方法来更改state。

const store = createStore({
  state: {
    count: 1,
    userinfo:{}
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    },
    //修改用户信息
    getUser(state,payload){
        state.userinfo = payload
    }
  }
})

通过一个state参数来实现改变状态。调用mutations下的increment方法来实现state.count自增1。

this.$store.commit('increment')

通过两个参数来更新状态,第二个参数payload。通过commit传递状态来更新。

this.$store.commit('getUser' ,{
    name:'admin',
    nickName:'hil'
})

//对象形式的写法
this.$store.commit({
    type:'getUser',
    name:'admin',
    nickName:'hil'
})

模板中使用更新的count

<template>
    <div>{{$store.state.count}}</div>
</template>
action

提交mutations ,而不是直接提交state。action是异步操作。

提交mutations

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

辅助函数mapActions

methods:{
    ...mapActions([
        'increment'
    ]),
    ...mapActions({
        add:'increment'
    })
}

执行更新

//直接分发
this.$store.dispatch('increment')

//通过mapActions来分发
this.increment()

//通过mapActions 设置别名的调用方法
this.add()

组合actions

将多个异步actions,进行组合执行。使用async/await 按顺序执行。

actions: {
  async one ({ commit }) {
    commit('gotData', await getData())
  },
  async two ({ dispatch, commit }) {
    await dispatch('one') // 等待 one 完成
    commit('gotData2', await getData2())
  }
}
modules

将store 分割成模块,避免一个store过大造成臃肿。实际上还是一个大的store,只是通过modules 将大的store分割成很多小的store。每个模块都拥有自己的 state、mutation、action、getter。

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

带上模块名使用

this.$store.state.a 

实例

本例简单创建一个vuex全流程的状态管理库,使用环境为vue2.x + vuex3.x。

main.js

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

store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import modelA from './modelA.js'
const store = new Vuex.Store({
    module:{
        a:modelA
    }
})

export default store

modelA.js

const modelA = {
    state:{
        number:0
    },
    mutations:{
        increment(state){
            state.number++
        },
        decrement(state) {
            state.number--
        }
    }
}

export default modelA

app.vue

<template>
    <div>
        <button @click="$store.commit('increment')">点击+1</button>
        {{$store.state.a.number}}
        <button @click="$store.commit('decrement')">点击-1</button>
    </div>
</template>
<script>
export default {
data(){
    return{}
},

}
</script>

如何在模块中避免冲突,了解vuex 命名空间