Vuex 学习笔记 01

239 阅读3分钟

Vuex 学习笔记 01

Vuex 介绍

1. 什么是 Vuex

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

说明:Vuex 是 vue 组件之间数据传递的方式,任意组件都可以使用

2. 什么是状态管理模式

状态自管理应用包含以下几个部分:

  • 状态(State): 驱动应用的数据源;
  • 视图(View): 以声明方式将状态映射到视图;
  • 操作(Actions): 响应在视图上的用户输入导致的状态变化。

安装、使用 Vuex

1. 安装 Vuex

// npm 安装
npm install vuex@next --save
// yarn 安装
yarn add vuex@next --save

2. 在项目的 src 文件下面创建 store 文件夹,store 文件夹下面 创建 store.js 文件 和 moudeles 文件夹。store.js 中的代码:

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

Vue.use(Vuex) // 将vuex安装到vue上 
const store = new Vuex.Store({ 
    modules:{ 
        app 
     } 
}) 

export default store; // 将 store 暴露出去

3. 在项目的 src 目录下 store 目录下的 moudeles 文件夹下面创建 app.js 文件,代码如下:

const app = { 
    state:{ // 全局状态 }, 
    mutations:{ // 修改状态的方法 }, 
    actions:{ // 异步提交mutation的方法 }, 
    getters:{ // 对store 的数据进行加工处理 类似计算属性 }
 } 
   
export default app; // 将 app 暴露出去

4. 在 main,js 文件中全局注册使用

import store from './store'

new Vue({ 
    store, // 全局使用 
    render:(h)=>h(App) 
}).$mount("#app")

核心概念

1. State

  • Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。
  • 说明:state 就是储存数据的仓库、容器

获取 state 数据

  • 直接获取: this.$store.store.xxx
  • mapState 辅助函数
    • 引入辅助函数: import { mapState } from 'Vuex'
    • 在计算属性中获取 state
      • computed: { ...mapState({ 'user' }) }
    • 使用 {{ user }}
  • 传参获取:computed: mapState({})
// store.js 文件代码
const store = { 
    state:{ user:'smaleLing' // 全局状态 },
} 
export default store;

// Home.Vue 文件代码 html 代码
<template>
    <h1>store里面的state用户名是:{{ $store.state.user }}</h1> // 直接获取全局状态数据
    <h1>store里面的state用户名是:{{ user }}</h1> // 对象展开运算符获取全局状态数据

    /**
    *<h1>store里面的state用户名是:{{ user1 }}</h1> // 辅助函数获取全局状态数据
    *<h1>store里面的state用户名是:{{ user2 }}</h1> // 辅助函数获取全局状态数据
    *<h1>store里面的state用户名是:{{ user3 }}</h1> // 辅助函数获取全局状态数据
    **/
</template>

// Home.Vue 文件代码 js 代码
<script>
import { mapState } from 'Vuex' // 引入辅助函数
export default {
  data() {
      return {
          msg:'data的数据'
      }
  },
  computed:{
      ...mapState({ 'user' }) // 对象展开运算符
  },
  
/**
* computed: mapState({
*  // 箭头函数可使代码更简练
*  user1: state => state.user,
*
*  // 传字符串参数 'user' 等同于 `state => state.user`
*  user2: 'user',
*
* // 为了能够使用 `this` 获取局部状态,必须使用常规函数
*  user3 (state) {
*    return state.user + this.msg
*  }
**/
  
}
</script>

2. Mutation

  • 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
  • 说明:mutations 里面装着一些改变数据方法的集合,就是把处理数据逻辑方法全部放在 mutations 里面,使得数据和视图分离。
  • 重要的原则: mutation 必须是同步函数

操作 mutation

  • 直接操作: this.$store.commit('mutation函数名')
  • 传递参数: this.$store.commit('mutation函数名','参数')
  • mapMutations 辅助函数
    • 引入辅助函数: import { mapMutations } from 'Vuex'
    • 在方法中操作 mutation
      • methods: { ...mapMutations(['add','sub']) }
    • 使用 this.add() this.sub(num) num 是传的参数
//store.js
const store ={
    state: {
	count: 1
    },
    mutations: {
        // 注册事件:type:add,handler 第一个参数是 state;
	add (state) { 
            // 变更状态
            state.count++
        },
        // 注册事件:type:sub,handler 第一个参数是 state, 第二个参数是 patload
        sub (state,payload) {
            state.count = payload - state
        }
    }
}

export default store;

// Home.Vue 文件代码 html 代码
<template>
    <button @click="add">+</button>
    <button @click="sub">-</button>
    <button @click="addMutations">辅助函数+</button>
    <button @click="subMutations">辅助函数-</button>
</template>

// Home.Vue 文件代码 js 代码
<script>
import { mapMutations } from 'Vuex'
export default {
    methods:{
        ...mapMutations(['add','sub']) 
	add(){
            // 调用 type(store里面函数名),触发 handler(state)
            this.$store.commit('increment');
        },
        sub(){
            // 调用 type(store里面函数名),触发 handler(state), 传参 payload
            this.$store.commit('sub',20);
            // 对象风格提交方式
            /**
            *  this.$store.commit({
            *    type: 'sub',
            *    payload: 20
            * })
            **/
        },
        addMutations(){
            this.add()
        },
        subMutations(){
            this.sub(20) // 直接传参
        }
    }
}
</script>

Action

Action 类似于 mutation,不同在于:

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

操作 action

  • 直接操作: this.$store.dispatch('action函数名')
  • mapActions 辅助函数
    • 引入辅助函数: import { mapActions } from 'Vuex'
    • 在方法中操作 action
      • methods: { ...mapActions(['add','sub']) }
    • 使用 this.add() this.sub(num) num 是传的参数
//store.js
const store ={
    state: {
	count: 1
    },
    mutations: {
        // 注册事件:type:add,handler 第一个参数是 state;
	add (state) { 
            // 变更状态
            state.count++
        },
        // 注册事件:type:sub,handler 第一个参数是 state, 第二个参数是 patload
        sub (state,payload) {
            state.count = payload - state
        }
    },
    actions: {
        // 定义异步操作 context 是最大的 store 
        asyncAdd (context) {
            setTimeout(()=>{
                context.commit('add')
            },500)
        },
        // 定义异步操作 payload 是传的参数 
        asyncSub (context,payload) {
            setTimeout(()=>{
                context.commit('sub',payload)
            },500)
        }
    }
}

export default store;

// Home.Vue 文件代码 html 代码
<template>
    <button @click="add">+</button>
    <button @click="sub">-</button>
    <button @click="addActions">辅助函数+</button>
    <button @click="subActions">辅助函数-</button>
</template>

// Home.Vue 文件代码 js 代码
<script>
import { mapActions } from 'Vuex'
export default {
    methods:{
      ...mapActions(['asyncAdd','asyncSub'])
      add(){
          // 触发 dispatch 直接调用 actions 
          this.$store.dispatch('asyncAdd');
        },
      sub(){
          // 触发 dispatch 直接调用 actions payload:20 传到 actions 的参数
          this.$store.dispatch('asyncSub',20);
          // 对象风格触发方式
          /**
          * this.$store.dispatch({
          *   context: 'asyncSub',
          *   payload: 20
          * })
          **/
        },
      addActions(){
          this.asyncAdd()
        },
      subActions(){
          this.asyncSub(20) // 直接传参
          // 对象风格提交方式: store.dispatch({payload: 20})
        }
    }
}
</script>

Getter

  • store 中的 state 中派生出一些状态
  • Vuex 允许我们在 store 中定义 'getter'(可以认为是 store 的计算属性)
  • 说明:对 state 里面的数据进行加工处理

使用 getter

  • 直接使用: this.$store.getters.属性
  • mapGetters 辅助函数
    • 引入辅助函数: import { mapGetters } from 'Vuex'
    • 在计算属性中使用 getter
      • : computed: { ...mapGetters(['todoCount']) }
// store.js 文件代码
const store = { 
    state:{ 
        user:'smaleLing',
        sex:'female'
    },
    getters:{
        updateInfo:(state) => {
            const info = '名字:' + state.user + '性别:' + state.sex
            return info
        }
    }
} 
export default store;

// Home.Vue 文件代码 html 代码
<template>
    <h1>用户信息:{{ $store.getters.updateInfo }}</h1> // 直接使用 getter
    <h1>用户信息:{{ updateInfo }}</h1> // 使用 mapGetters 辅助函数
</template>

// Home.Vue 文件代码 js 代码
<script>
import { mapGetters } from 'Vuex' // 引入辅助函数
export default {
  computed:{
      ...mapGetters(['updateInfo']) // 对象展开运算符
  },
}
</script>

Module

  • Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。
  • 随着项目的复杂度增大,为了方便管理vuex,一般会将其按功能分割成不同的模块(module),方便日后管理。
  • 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块

项目结构

src
└── store
    ├── index.js          // 组装模块并导出 store 
    ├── mutations.js      // 根级别的 mutation
    ├── actions.js        // 根级别的 action
    ├── getters.js        // 根级别的 getters
    └── modules
        ├── login.js      // 登录模块
        └── users.js      // 用户模块
// index.js 代码
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
import login from './modules/login'
import users from './modules/users'


Vue.use(Vuex)

const store = new Vuex.Store({
  // 根节点
  mutations,
  getters,
  actions,
  // 模块
  modules: { 
    users,
    login
  }
})

export default store;

// login.js 代码
const login = {
    state:{ // 全局状态 }, 
    mutations:{ // 修改状态的方法 }, 
    actions:{ // 异步提交mutation的方法 }, 
    getters:{ // 对store 的数据进行加工处理 类似计算属性 }
}

export default login;

// users.js 代码
const login = {
    state:{ // 全局状态 }, 
    mutations:{ // 修改状态的方法 }, 
    actions:{ // 异步提交mutation的方法 }, 
    getters:{ // 对store 的数据进行加工处理 类似计算属性 }
}

export default users;

  • @Title: Vuex 学习笔记 01
  • @Content: Vue
  • @Autor: ling.wang
  • @StudyDate: 2022-02-22 ~ 2022-02-22
  • @WritingDate: 2022-02-23