Vuex
Vuex 状态管理
Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
Vuex 主要解决的问题
- 多个视图依赖同一个状态
- 来自不同视图的行为需要变更同一个状态
使用 Vuex 的好处
- 能够在
vuex
中集中管理共享的数据,易于开发和后期维护 - 能够高效地实现组件之间的数据共享,提高开发效率
- 在
vuex
中的数据都是响应式的
Vuex 基础使用
- 安装 vuex 依赖包
- npm install vuex --save
- 导入 vuex 包
- import Vuex from 'vuex'
Vue.use(Vuex)
- 创建 store 对象
-
const store = new Vuex.Store({
// state 中存放的就是全局共享的数据 state: { count: 0 }
})
-
- 将 store 对象挂载到 vue 实例中
store/index.js文件(外部import./store时会自动访问此目录下的index.js文件):
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
// 在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理
strict:products.env.NODE_ENV !== 'production',
// 状态
state: {
},
// 用来处理状态
mutations: {
},
// 用于异步处理
actions: {
},
// 用来挂载模块
modules: {
}
})
要使用 store 就在把 store 挂载到 Vue 中
把 store 挂载到 Vue 之后 ,所有的组件就可以直接从 store 中获取全局数据了
import Vue from 'vue'
import App from './App.vue'
import store from './store'//默认访问此文件中的index.js文件
Vue.config.productionTip = false
new Vue({
// 挂载到vue 中
store,
render: (h) => h(App),
}).$mount('#app')
Vuex的5大属性
1.state
在 state 中添加数据
我们需要共享的状态都放在写在 state 对象里面
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {},
actions: {},
modules: {},
})
获取到 state
有两种方式
1.直接使用 this.$store.state[属性]
,(this
可以省略)
2.使用 mapState
通过 mapState
把 store
映射到 组件的计算属性,就相当于组件内部有了 state
里的属性
//法1:
<template>
<div id="app">
{{ this.$store.state.name }}
{{ this.$store.state.age }}
</div>
</template>
//法2
<template>
<div id="app">
{{ name }}
{{ age }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
}
}
</script>
<style scoped>
</style>
2.Mutation
Store
中的状态不能直接对其进行操作,我们得使用 Mutation
来对 Store
中的状态进行修改,虽然看起来有些繁琐,但是方便集中监控数据的变化
如果想要定义的方法能够修改 Store
中的状态,需要参数就是 state
state
的更新必须是 Mutation
来处理
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {
// 在这里定义 方法
/**
*
* @param {*} state 第一个参数是 Store 中的状态(必须传递)
* @param {*} newName 传入的参数 后面是多个
*/
changeName(state, newName) {
// 这里简单举个例子 修改个名字
state.name = newName
},
},
actions: {},
modules: {},
})
在组件中使用 mutations 中的方法,同样有两种方法在组件触发 mutations
中的方法
1.this.$store.commit() 触发
在 methods
中定义一个方法,在这个方法里面通过this.$store.commit触发 mutations
中的方法
<template>
<div id="app">
<button @click="handleClick">方式1 按钮使用 mutation 中方法</button>
{{ name }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
},
methods: {
handleClick() {
// 触发 mutations 中的 changeName
this.$store.commit('changeName', '小浪')
}
},
}
</script>
<style scoped>
</style>
2.使用 mapMutations
<template>
<div id="app">
<button @click="changeName('小浪')">方式2 按钮使用 mutation 中方法</button>
{{ name }}
</div>
</template>
<script>
// 从 Vuex 中导入 mapState
import { mapState, mapMutations } from 'vuex'
export default {
name: 'App',
computed: {
// 将 store 映射到当前组件的计算属性
...mapState(['name', 'age'])
},
methods: {
// 将 mutations 中的 changeName 方法映射到 methods 中,就能直接使用了 changeName 了
...mapMutations(['changeName'])
},
}
</script>
<style scoped>
</style>
3.Action
Action
和 Mutation
区别
Action
同样也是用来处理任务,不过它处理的是异步任务,异步任务必须要使用 Action
如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发 Mutation 的方式间接变更数据。
/* src/store/index.js */
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: '张三',
age: 21,
},
mutations: {
// 在这里定义 方法
/**
*
* @param {*} state 第一个参数是 Store 中的状态(必须传递)
* @param {*} newName 传入的参数 后面是多个
*/
changeName(state, newName) {
// 这里简单举个例子 修改个名字
state.name = newName
},
},
actions: {
/**
*
* @param {*} context 上下文默认传递的参数
* @param {*} newName 自己传递的参数
*/
// 定义一个异步的方法 context是 store
changeNameAsync(context, newName) {
// 这里用 setTimeout 模拟异步
setTimeout(() => {
// 在这里调用 mutations 中的处理方法
context.commit('changeName', newName)
}, 2000)
},
},
modules: {},
})
在组件中是 Action 中的异步方法也是有两种方式
1.this.$store.dispatch()
// 定义 Action
const store = new Vuex.Store({
// ...省略其他代码
mutations: {
addN(state, step) {
state.count += step
}
},
actions: {
addNAsync(context, step) {
setTimeout(() => {
context.commit('addN', step)
}, 1000) }
} })
// 触发 Action methods: {
handle() {
// 在调用 dispatch 函数,
// 触发 actions 时携带参数
this.$store.dispatch('addNAsync', 5)
} }
//this.$store.dispatch() 是触发 actions 的第一种方式
//触发 actions 的第二种方式:
// 1. 从 vuex 中按需导入 mapActions 函数
import { mapActions } from 'vuex'
//通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法:
// 2. 将指定的 actions 函数,映射为当前组件的 methods 函数
methods: {
...mapActions(['addASync', 'addNASync']) }
4.Getter
Getter
类似于计算属性,但是我们的数据来源是Vuex
中的state
,所以就使用Vuex
中的Getter
来完成- Getter 用于对 Store 中的数据进行加工处理形成新的数据
- Store 中数据发生变化,Getter 的数据也会跟着变化。
Getter
也有两种方式导入
1.this.$store.getters[名称]
2.使用 mapGetters
// 定义 Getter
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
showNum: state => {
return '当前最新的数量是【'+ state.count +'】'
}
}
})
//使用 getters 的第一种方式:
this.$store.getters.名称
//使用 getters 的第二种方式:
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['showNum'])
}
5.Module
为了避免在一个复杂的项目 state
中的数据变得臃肿,Vuex
允许将 Store
分成不同的模块,每个模块都有属于自己的 state
,getter
,action
,mutation
Vuex的严格模式是什么,有什么作用,怎么开启?
在严格模式下,无论何时发生了状态变更且不是由 mutation函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
在Vuex.Store 构造器选项中开启
const store = new Vuex.Store({
strict:true,
})
怎么引用Vuex?
- 先安装依赖
nnpm install vuex --save
- 在项目目录src中建立store文件夹
- 在store文件夹下新建index.js文件,写入
导入 vuex 包
import Vuex from 'vuex'
Vue.use(Vuex)
创建 store 对象
const store = new Vuex.Store({
// state 中存放的就是全局共享的数据 state: { count: 0 }
})
将 store 对象挂载到 vue 实例中