Vuex
介绍
Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式 ,Vuex是实现组件全局状态(数据)管理的一种
机制,可以方便的实现组件之间的数据共享。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐
冗余的。如果您的应用够简单,最好不要使用Vuex。
使用Vuex管理数据优势:
- 能够在vuex中 集中管理共享的数据 ,便于开发和后期进行维护
- 能够高效的实现组件之间的数据共享,提高开发效率
- 存储在vuex中的数据是 响应式 的,当数据发生改变时,页面中的视图也会同步更新
- vuex中的数据操作可以在开发阶段通过开发调试工具来进行追踪,便于开发
EventBus虽然也能实现,但是不能追踪不知道谁发的指令,数据不能保持
核心概念
vuex对象中通过 state 来存储状态,除了state以外还有用来操作state中数据的方法集,以及当我们需
要对state中的数据需要加工的方法集等等成员。
成员列表: - 😃state 存放状态(数据) 必须的
- 😃mutations 对于state成员进行同步修改操作,可以异步
- getters 获取state中的数据,类似于组件中的计算属性
- 😃actions 进行异步操作,异步得到结果后通知mutation修改state成员
- 😃modules 模块化状态管理,多状态文件管理时使用(一般写一次)
在src下新建store/index.js。
import vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const store = new Vuex.Store({
state: {
bankINF:{'name':'我是vuex的第一个数据',‘ID:100.’bankName‘:'中国银行'}
}
})
export default store
首先,Vue组件如果调用某个VueX的方法过程中需要向后端请求时或者说出现异步操作时,需要
dispatch VueX中actions的方法,以保证数据的同步。可以说,action的存在就是为了让mutations中
的方法能在异步操作中起作用。
如果没有异步操作,那么我们就可以直接在组件内提交状态中的Mutations中自己编写的方法来达成
对state成员的操作。不建议在组件中直接对state中的成员进行操作,这是因为直接修改(例如:
this.$store.state.name = ‘hello’)的话不能被VueDevtools所监控到。最后被修改后的state成员会被渲
染到组件的原位置当中去。
使用Vuex的注意事项:
11. 数据流都是单向的
12. 组件能够调用action
13. action用来派发mutation
14. 只有mutation可以改变状态
15. store是响应式的,无论state什么时候更新,组件都将同步更新
安装与配置
方案1:在使用vue-cli命令创建项目时,勾选上vuex选项,即安装上vuex插件(推荐)
方案2:通过后续的npm来进行安装
手动创建仓库文件
常规情况下
npm i -S vuex@3
import Vue from ‘vue’
import Vuex from ‘vuex’ Vue.use(Vuex) export default new Vuex.Store({
state: { },mutations: { },actions: { },getters: { },modules: { } })
一般在 src/store/index.js
index.js就是vuex的仓库
```javascript
index.js // 此目录就为vuex数据目录
import Vue from 'vue'
import Vuex from 'vuex'
// 插件方式插入到Vue类中
Vue.use(Vuex)
const store = new Vuex.Store({ state: { count: 1 }})
export default store
需要在 src/main.js 中引入store
import Vue from 'vue'
import App from './App.vue'
// 路由
import router from './router'
// vuex
import store from './store'
// 全局样式
import './style/global.scss' Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
在main.js中注册store
import store from './store/index'
new Vue({
el:'app',
router,
store,
template:'<App>',
components:{app}
)}
在组件中获取vuex中的数据
在组件中可以通过 this.$store 得到vuex中的 state 数据。
mutations同步修改数据(state)
一条重要的原则就是要记住 mutation 必须是同步函数, 每一条 mutation 被记录,devtools 都需要捕捉
到前一状态和后一状态的快照。如果是异步函数中的回调让这不可能完成,因为当 mutation 触发的时
候,回调函数还有可没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回
调函数中进行的状态的改变都是不可追踪的。
mutations专门用来修改状态值的方法集合,mutations中的东西是专门修改数据(state)的
mutations不支持异步
官方文档中这样写道
Mutation 必须是同步函数 一条重要的原则就是要记住 mutation 必须是同步函数 <template> <div> <h3>home页面</h3> <div>vuex中的数据 : {{ $store.state.count }}</div> </div> </template> <script> export default { mounted() { //console.log(this.$store) }}</script> <style lang="scss" scoped></style>
state 即vuex中的第一个方法,存放状态(数据) 即初始
payload 载荷,使用 mutations 修改数据,你可以向 store.commit 传入额外的参数,即
mutation 的载荷(payload) commit :同步操作,数据提交至 mutations
对应的函数在mutations;
commit ====>用法是 this.$store.commit('setCount', 1);
actions异步操作
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态
Action 可以包含任意异步操作
```javascript
引入vue.config中可以配置服务,内置了express
同步可以直接调用$store中commit this.$store.commit('setCount', 1);
// 参数1:让mutation操作的名称
// 参数2:传给mutation的数据 从而引发store/index中的mutations去修改vuex中的state中初始数据 mutations:{ 方法名(state,payload){ 改变state值的方法 } }
// vue.config.js它是vue工程给开发者暴露出来用于修改webpack配置所用
// 修改此文件一定要重启项目
// 它是给nodejs运行,所以要使用commonjs规范 const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, // 配置服务 -- 内置express devServer: { // 前置请求
beforeonBeforeSetupMiddleware({ app }) { app.get('/api/users', (req, res) => { res.send({ code: 0, msg: 'ok', data: [ { id: 1, name: '张三', age: 18 }, { id: 2, name: '李四', age: 22 } ] }) }) }}})
专门用来调用mutation然后修改数据(state)的
由于异步首先要修改就要在调用
s
t
o
r
e
中
使
用
d
i
s
p
a
t
c
h
t
h
i
s
.
store中使用dispatch this.
store中使用dispatchthis.store.dispatch(‘fetchUserAction’, 1000); // 参数1:定义actions的类型名称 // 参数2:参数,可选 从而引发actions之后再去调用store中commit去调用mutations再去修改vuex中的state中初始数据 actions:{ 方法名(store,payload){ store.commit(mutations中的方法名,传递参数(即payload)) } } store 第一个参数其实是context,固定不变的,context就是一个与store实例具有相同方法的属
性,即:store的对象context,如果想限定只能使用context中的属性或者方法,则需要使用{}来
限定,如:{commit}。
payload 载荷,使用 mutations 修改数据,你可以向 store.commit 传入额外的参数,即
mutation 的载荷(payload) dispatch :含有异步操作,数据提交至 actions
对应的函数在actions;
this.$store.dispatch(‘fetchUserAction’, 1000);
渲染页面更好的应该更加依赖与计算属性
举个栗子
home页面
- {{ item.name }}–{{ item.age }}
我们会发现
与
是一样的
mutations与actions对比
},mounted() { // 参数1:定义actions的类型名称 // 参数2:参数,可选 this. KaTeX parse error: Expected 'EOF', got '}' at position 41: …Action', 1000) }̲,methods: { inc…store.commit(‘setCount’, 2) } } }
- {{ item.name }}
- {{ item.name }}–{{ item.age }}
- 加上计算属性 computed:{ users(){ return this.
KaTeX parse error: Expected 'EOF', got '}' at position 19: …re.state.users }̲ } Vuex简化流程: ge…store.state.count.num
value 它就是你小的vuex的模块对象
无命名空间
强制命名空间(同样使用命名空间的是 socket.io ) namespaced: true,
例如
// 独立的vuex的数据模块 export default { // 强制开启命名空间,模块中的名称就无须考虑全局中是否有同名的情况s namespaced: true, state: { test: ‘’, num: 100 },getters: { getNum({ num }) { return num } },mutations: { // 在没有开启强制命令空间时,mutation或actions或getters中的名称不要重名
强制命名空间不会对 state 有影响
辅助函数
vuex提供了辅助函数处理庞大的vuex数据,mapState,mapGetters,mapMutations,
mapActions,实际就是把state、getters、mutations、actions整合成一个 数组 ,一次性返回
语法糖,四大金刚辅助函数:mapState(对应state),mapGetters(对应Getters),
mapActions(对应Actions),mapMutations(对应Mutations) 1. mapState
addNum(state, data) { // console.log(‘count’) state.num += data } } }import axios from ‘axios’ export default { namespaced: true, state: { num: 0, users: [] },mutations: { addUsers(state, data) { state.users = data } },actions: { async fetchUserApi({ commit }, data) { let ret = await axios.get(‘/api/users’) // 如果在当前模块中,则无论是否有开启强制命名空间模式,它都无须使用命名空间 commit(‘addUsers’, ret.data.data) } } }
16. mapGetters
17. mapActions
18. mapMutations
注:模块化后,开启了namespaced:true 配置后,注意方法的调用有2个参数
注:四个辅助函数在组件中使用:
mapState,mapGetters返回的是属性,所以混入到 computed 中
mapMutations,mapActions返回的是方法,只能混入到methods中
如果要是用辅助函数就要在所用试图vue中先引入辅助函数
import { mapState, mapGetters, mapActions, mapMutations } from “vuex”; export default { computed: { …mapGetters({ “”: “vuex仓库定义的方法”, }), …mapState({}), },methods: { …mapMutations({}), …mapActions({}), }, };
mapState在计算属性中使用
强制命名空间 …mapState(‘count’,[‘num’])
无命名空间 …mapState([‘num’])
其余辅助函数用法类似
mapMutations/mapActions的使用方法(以下都为命名空间的写法)
…mapMutations(‘count’, { addNum: ‘addNum’ }), 或 …mapMutations(‘count’, [‘addNum’]), …mapActions(‘user’,{fetchUserApi:‘fetchUserApi’}) 或 …mapActions(‘user’, [‘fetchUserApi’])
使用mapMutations/mapActions中的方法直接使用第mapMutations/mapActions中的第二个参
数(无命名空间就是第一个参数)中的名字即可
如下所示
methods: { // …mapMutations(‘count’, { addNum: ‘addNum’ }), …mapMutations(‘count’, [‘addNum’]), incr() { // 开启强制命令空间的commit // this.$store.commit(‘count/addNum’, 2) this.addNum(3)//()中就是载荷,直接传值就可以 }}
下图就是四个辅助函数的基本使用方法