每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
1、安装vuex
口诀:“233”、“344”
数字分别对应,“vue版本,vue 路由版本、vuex 版本”。
所以这里了使用vuex3版本:
yarn add vuex@3

2、创建仓库文件

编写如下:
- // 这个文件用于存放vuex的核心代码
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- // 插件安装
- Vue.use(Vuex)
-
- // 创建仓库
- const store = new Vuex.Store()
-
- // 导出仓库,把仓库丢到main.js
- export default store
3、在main.js中导入
- import Vue from 'vue'
- import App from './App.vue'
- import router from './router'
- import store from '@/store/index'
-
- Vue.config.productionTip = false
-
- new Vue({
- router,
- render: h => h(App),store
- }).$mount('#app')
4、验证仓库是否被创建成功
- created () {
- console.log('222222')
- console.log(this.$store)
- },
控制台打印:
这个对象就是我们的仓库了

state是vuex的核心。
状态目标:明确如何给仓库提供数据。
如何使用仓库的数据?方式有两种:
步骤1:提供数据State
提供唯一的公共数据源,所有共享的数据都要统一放到 Store中的 State中存储。在 state对象中可以添加我们要共享的数据。

步骤2:获取数据:

示例:
1、在我们的vuex仓库中添加共享的数据
- // 这个文件用于存放vuex的核心代码
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- // 插件安装
- Vue.use(Vuex)
-
- // 创建仓库
- const store = new Vuex.Store({
- // 通过提供数据,这些数据被所有的组件共享
- state: {
- title: '公共的标题',
- count: 100
- }
- })
-
- // 导出仓库,把仓库丢到main.js
- export default store
2、在我们的页面中获取数据
<h1>{{ $store.state.title }}h1>

简化mapstate是辅助函数,帮助我们把 store中的数据自动映射到组件的计算属性中。


步骤1:
- import { mapState } from 'vuex'
- // console.log(mapState(['count','title']))
- // 我们可以在计算属性中展开mapState
步骤2:
- computed: {
- ...mapState(['count', 'title'])
- },
步骤3:
我们可以像使用vue的data中的数据一样,去使用计算属性中的变量。
<h1>{{ title }}h1>

明确νuex同样遵循单向数据流,组件中不能直接修改仓库的数据通过 strict:true可以开启严格模式
- // 创建仓库
- const store = new Vuex.Store({
- // 严格模式: 如果每个组件都可以修改数据,一旦项目打了,开发人员多了,就很难维护了
- // 可以使用严格模式来让vuex修改数据,修改后,vuex在通知我们的组件,更新数据。
- // 有利于初学者,检测不规范的代码=>上线时需要关闭
- strict: true,
- // 通过提供数据,这些数据被所有的组件共享
- state: {
- title: '公共的标题',
- count: 100
- }
- })
state数据的修改只能通过 mutations。

1、仓库index.js
- const store = new Vuex.Store({
- strict: true,
- state: {
- title: '公共的标题',
- count: 100
- },
- mutations: {
- // 所有 mutation函数,第一个参数,都是 state
- addCount (state) {
- state.count += 1
- }
- }
- })
2、在页面中使用我们的mutations
- handleAddCount(){
- this.$store.commit('addCount')
- }
<button @click="handleAddCount">值 + 1button>


需要注意的是,如果要传递多个参数,我们需要把多个参数丢到对象当中,像传递一个参数一样,把对象传递给我们定义的mutations函数 。
目标:掌握辅助函数 mapmutations,映射方法mapmutations和 mapstate很像,它是把位于 mutations中的方法提取了出来,映射到组件 methods中

mapmutations相当于3.1的辅助写法,只是把方法捞到了methods当中了。
目标:明确 actions的基本语法,处理异步操作,
需求:一秒钟之后,修改 state的 count成666。
说明: mutations必须是同步的(便于监测数据变化,记录调试。
步骤1:修改仓库index.js
- mutations: {
- changeTitle (state, newTitle) {
- state.title = newTitle
- }
- },
- // 3.actions 处理异步
- // context上下文(此处未分模块,可以当成 store仓库)
- // context, commit(" mutation名字,额外参数)
- actions: {
- asynChangeTitle (context, newTitle) {
- // setTimeout方法是异步的,3秒钟之后换成我们的新标题
- setTimeout(()=>{
- context.commit('changeTitle',newTitle)
- },3000)
- }
- }
这里,actions是mutations的同级对象。
步骤2: 测试
<button @click="handleChangeTitle">3秒之换标题button>
- methods: {
- handleChangeTitle () {
- // 调用action
- //this.$store.dispatch('我们vuex仓库中的action的名字','额外参数')
- this.$store.dispatch('asynChangeTitle','这是3秒钟之后的新标题')
- }
- },

总结:和前面的“mutations传参语法”目录类似,只是多了actions这个中间人 ,this.$store.commi换成了this.$store.dispatch。
getters类似于计算属性。说明:除了 state之外,有时我们还需要从 state中派生出一些状态,这些状态是依赖 state的,此时会用到 getters。
例如: statel中定义了list,为1-6的数组,组件中,需要显示所有大于3的数据
步骤1:
getters和state同级
- getters: {
- filterList (state) {
- return state.list.filter(item => item > 3)
- }
- },
步骤2:
在组件内使用:
import { mapState,mapGetters } from 'vuex'
- computed: {
- //mapState和mapGetters都是映射属性
- ...mapState(['count', 'title']),
- ...mapGetters(['filterList'])
- },

项目大,代码就多了,store的文件内存上千行代码,很难维护,不易管理。
module的存在就是为了解决这个问题的。
步骤1:
在store目录下建一个新目录modules,在modules下建两个js文件,user.js,setting.js,如下:
- // setting.js
- const state = {
- theme: 'blue',
- desc: 'deom'
- }
- const mutations = {}
-
- const actions = {}
-
- const getters = {}
-
- export default {
- state,
- mutations,
- actions,
- getters
- }
- // user.js
- const state = {
- name: 'Mike',
- hobby: '唱、跳、Rap'
- }
- const mutations = {}
-
- const actions = {}
-
- const getters = {}
-
- export default {
- state,
- mutations,
- actions,
- getters
- }
步骤2、把user.js,setting.js导入到store目录下的index.js文件中:
- import settings from './modules/settings'
- import user from './modules/user'
mudules对象和state对象同级:
- modules:{
- settings,
- user
- }
步骤3 使用modules下的数据:
modules的子模块的状态,还是会挂到根级别的 state使用模块中的数据
①直接通过模块名访问$ store. state模块名.XXX
②通过 mapstate映射
默认根级别的映射 mapstate(['XXX'])子模块的映射 mapstate('模块名',['XXX']) -
需要开启命名空间
- export default {
- state,
- mutations,
- actions,
- getters,
- namespaced:true
- }
<span>爱好: {{ $store.state.user.hobby }}span>

<span>(mapState)爱好: {{ user.hobby }}span>
- computed: {
- //mapState和mapGetters都是映射属性
- ...mapState(['count', 'title','settings','user']),
- ...mapGetters(['filterList'])
- },

步骤1、定义mutaion
- const mutations = {
- setUserInfo(state,newHobby){
- state.hobby = newHobby
- }
- }
- methods: {
- updateUserInfo () {
- // this.$store.commit('模块名/mutation名',参数)
- this.$store.commit('user/setUserInfo','唱、跳、Rap、Smile')
- }
- },
-
- <span>爱好: {{ user.hobby }}span>
点击按钮前:

点击按钮后的页面: