以项目的视角使用Vuex,一文彻底用会Vuex

博主前面在 图解Vue组件通讯【一图胜千言】 介绍过父子组件之间的通信、兄弟组件之间的通信、祖先与后代组件之间的通信,但在实际开发过程中,也会遇到非关系组件之间的通信,这时候就需要使用 vuex 这一独立于组件的状态管理工具了。

本文以项目的视角讲解Vuex的使用,讲解概要如下:

创建Vuex、挂载Vuex
state 公共数据源
mutations 修改数据源
actions 异步操作
getters 计算属性
getters和computed 的组合使用
modules 模块
小结

1. 创建vuex、挂载vuex

1.1 安装vuex

npm i vuex@3.6.2

1.2 项目的src目录下,新建store目录 \ index.js :

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'  // 全局getters,后文说明
import goods from './modules/goods'  // 自定义模块,后文说明

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters,
  mutations: {
  },
  actions: {
  },
  modules: {
    goods
  }
})

1.3 在入口文件main.js中挂载store

import store from '@/store'
		
new Vue({
    store,
	router
	....
}).$mount('#app')

2. state 公共数据源

2.1 state称为公共数据源,需要共享的数据统一放在state进行储存(类似data)。
项目中基本使用独立模块、独立作用域的state,例如:

在store目录下 \ 新建modules目录 \ goods.js...

// goods.js
export default {
  state: {
    name: 'Apple Version Pro'
  },

  getters: {
  },

  mutations: {
  },

  actions: {
  },

  namespaced: true  // 开启命名空间,隔离作用域

}

2.2 组件中获取modules下的state

$store.state.模块名.键名
$store.state.goods.name

3. mutations 修改数据源

3.1 mutations 是修改state数据的唯一节点,并且mutations必须是同步的

3.2 创建mutations时,不携带参数

// goods.js
export default {
  state: {
    price: 2999
  },

  getters: {
  },

  mutations: {
    increasePrice (state) {
      state.price++
    }
  },

  actions: {
  },

  namespaced: true  // 开启命名空间,隔离作用域

}

3.3 使用modules中的的mutations,不传参

$store.commit('模块名/mutation名')
$store.commit('goods/increasePrice')

3.4 创建mutations时,携带参数

// goods.js
export default {
  state: {
    price: 2999
  },

  getters: {
  },

  mutations: {
    // 参数1是state, 参数2是传参
	// 只存在1个传参, 多个传参使用数组或对象
    increasePriceN (state, num) {
      state.price += num
    }
  },

  actions: {
  },

  namespaced: true  // 开启命名空间,隔离作用域

}

3.5 使用modules中的的mutations,传参

$store.commit('模块名/mutation名', 参数)
$store.commit('goods/increasePriceN', 199)

4. actions 异步操作

一般在actions里声明函数,函数中可以包含任何异步操作,最后提交mutations,不允许直接修改state数据源。

// goods.js
export default {
  state: {
    name: 'Apple Version Pro'
  },

  getters: {
  },

  mutations: {
    setGoodsName (state, val) {
      state.name = val
    }
  },

  actions: {
    // 参数1是context, 参数2是传参
	// 只存在1个传参, 多个传参使用数组或对象
    asyncSetGoodsName (context, val) {
      setTimeout(() => {
        // context.commit可以访问到当前作用域下全部的mutations方法
        context.commit('setGoodsName', val)
      }, 3000)
    }
  },

  namespaced: true  // 开启命名空间,隔离作用域

}

使用modules中的的actions:

$store.dispatch('模块名/actions名', 参数)
$store.dispatch('goods/asyncSetGoodsName', 'Samsung')

5. getters 计算属性

类似于vue中的computed,进行缓存,对state的数据进行加工处理形成新的数据。

示例:

// goods.js
export default {
  state: {
    nums: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  },

  getters: {
    // 参数是state,不支持更多参数
	// 必须要有返回值!!!
    largeNums (state) {
      return state.list.filter(item => item > 5)
    }
  },

  mutations: {
  },

  actions: {
  },

  namespaced: true  // 开启命名空间,隔离作用域

}
// 此处是[]
$store.getters['模块名/getters名']
$store.getters['goods/largeNums']

6. getters和computed 的组合使用

项目中一般会把 `组件的computed` 和 `Vuex的getters` 组合起来使用。这样当 getters 中的相关状态发生变化时,computed 属性会自动重新计算。这样可以确保您的组件在依赖的状态发生变化时得到更新。

示例:

6.1 在store目录下新建 getters.js

// 使用getters监听state变化,实时同步给组件的computed,无需重新获取state
const getters = {
  // name为state的键名
  // goods为模块名
  name: state => state.goods.name,
  price: state => state.goods.price
}
export default getters

6.2 在 store \ index.js 中挂载全局的getters

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'  // 全局getters
import goods from './modules/goods'  // 自定义模块

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters,  // 挂载 getters
  mutations: {
  },
  actions: {
  },
  modules: {
    goods
  }
})

6.3 语法

this.$store.getters.键名
this.$store.getters.name
this.$store.getters.price

6.4 代码片段 

// 组件A
<template>
  <div>
    <h2>{{ goodsName }}</h2>
    <h2>{{ goodPrice }}</h2>
  <div>
</template>

<script>
export default {
  name: 'App',
  computed: {
    goodsName() {
      return this.$store.getters.name
    },
    goodsPrice() {
      return this.$store.getters.price
    }
  }
}
</script>

// 组件B
<template>
  <div><div>
</template>

<script>
export default {
  name: 'MyComponent',
  created () {
    // 使用模块中的mutations方法同步修改state数据源,getters和computed的组合会同步刷新数据
    this.$store.commit('goods/increasePriceN', 199)
  }
}
</script>

7. modules 模块

使用单一的状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿,所以有了vuex的模块化。



基本用法:
1. store目录下 \ 新建modules目录:创建模块,
例如 goods.js \ person.js,
拆分模块后,每个模块都有自己独立作用域的state、mutations、actions、getters...

2. store目录下 \ index.js 中配置modules

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import goods from './modules/goods'  // 自定义模块A
import person from './modules/person'  // 自定义模块B

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters,
  mutations: {
  },
  actions: {
  },
  modules: {
    goods,  // 自定义模块A
    person  // 自定义模块B
  }
})

8. 小结

8.1 什么是vuex

状态 (数据) 集中管理工具

8.2 什么样的数据适合放在vuex中? 

多组件共享的数据

8.3 属性

state: 公共数据源
mutations: 修改公共数据源的唯一节点
actions: 涉及到异步操作放到actions中,包含任何异步操作,提交的是mutations,不能直接修改数据
getters: 基于state派生出的新数据写在这里

8.4 Tips

由于单一状态树,所有的共享数据都放在一个state中,导致state冗余,后期维护性较差,建议拆分模块。modules每个模块都有自己的state,mutations,actions,getters,为了防止协同开发出现的命名冲突问题,一般会为各个模块开启命名空间 namespaced: true

End-----------------------

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值