每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
-
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
vuex初步使用
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仓库的数据
state是vuex的核心。
状态目标:明确如何给仓库提供数据。
如何使用仓库的数据?方式有两种:
1、通过store直接访问
步骤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>
2、通过辅助函数访问
简化mapstate是辅助函数,帮助我们把 store中的数据自动映射到组件的计算属性中。
步骤1:
import { mapState } from 'vuex'
// console.log(mapState(['count','title']))
// 我们可以在计算属性中展开mapState
步骤2:
computed: {
...mapState(['count', 'title'])
},
步骤3:
我们可以像使用vue的data中的数据一样,去使用计算属性中的变量。
<h1>{{ title }}</h1>
3、严格模式
明确νuex同样遵循单向数据流,组件中不能直接修改仓库的数据通过 strict:true可以开启严格模式
// 创建仓库
const store = new Vuex.Store({
// 严格模式: 如果每个组件都可以修改数据,一旦项目打了,开发人员多了,就很难维护了
// 可以使用严格模式来让vuex修改数据,修改后,vuex在通知我们的组件,更新数据。
// 有利于初学者,检测不规范的代码=>上线时需要关闭
strict: true,
// 通过提供数据,这些数据被所有的组件共享
state: {
title: '公共的标题',
count: 100
}
})
4 mutations的操作流程
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">值 + 1</button>
5 mutations传参语法
需要注意的是,如果要传递多个参数,我们需要把多个参数丢到对象当中,像传递一个参数一样,把对象传递给我们定义的mutations函数 。
6 辅助函数: mapmutations
目标:掌握辅助函数 mapmutations,映射方法mapmutations和 mapstate很像,它是把位于 mutations中的方法提取了出来,映射到组件 methods中
mapmutations相当于3.1的辅助写法,只是把方法捞到了methods当中了。
7 actions (异步操作)
目标:明确 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。
8 getters
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'])
},
9 模块 module(进阶语法)
9.1 获取module的数据
项目大,代码就多了,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
}
①直接通过模块名访问$store.state.模块名.XXX
<span>爱好: {{ $store.state.user.hobby }}</span>
②通过mapstate映射
<span>(mapState)爱好: {{ user.hobby }}</span>
computed: {
//mapState和mapGetters都是映射属性
...mapState(['count', 'title','settings','user']),
...mapGetters(['filterList'])
},
9.2 修改module模块下的数据
步骤1、定义mutaion
const mutations = {
setUserInfo(state,newHobby){
state.hobby = newHobby
}
}
methods: {
updateUserInfo () {
// this.$store.commit('模块名/mutation名',参数)
this.$store.commit('user/setUserInfo','唱、跳、Rap、Smile')
}
},
<button @click="updateUserInfo"> 修改爱好信息 </button>
<span>爱好: {{ user.hobby }}</span>
点击按钮前:
点击按钮后的页面: