vuex介绍
- vuex的作用是解决多组件状态共享的问题,在大型的项目中,组件通讯会变得很混乱,使用vuex可以统一管理组件之间的通讯
- 它是
独立于组件而单独存在的,所有的组件都可以把它当作一座桥梁来进行通讯。
使用vuex好处
- 实现全局组件的数据共享
响应式: 只要vuex中的数据变化,对应的组件会自动更新(类似于vue数据驱动)- 操作更简洁 : 类似于sessionStorage,只有几个方法
vuex使用场景
- 开发中我们组件传值大多还是使用父子组件传值,少部分才使用vuex 比如:数据需要在非常多的页面使用 如用户头像 全局设置....
- 不是所有的场景都适用于vuex,只有在必要的时候才使用vuex,如果
不必要,尽量别用 - 使用了vuex之后,会一定程度上增加了项目的复杂度
- 适合使用vuex场景
- 这个数据需要在
很多个地方使用,如果采用组件传值方式,写起来很麻烦,而且多个地方都要写 - .不适合使用vuex场景
- 这个数据
不需要多个地方使用,如果某个数据仅仅只是在两个组件之间通讯,优先使用props或$emit
那我们总结一下:
vuex的作用简单来说就是实现所有组件数据共享 一旦vuex数据修改,所有使用的地方数据都会自动更新
vuex使用流程
使用步骤:
vue-cli中整合==(如果使用vue ui创建创建,直接勾选vuex,会自动帮我们完成配置)- vue add vuex :
- 1.如果提示选择 y,
- 2.创建了
/src/store/index.js, - 3.
main.js导入并挂载到Vue实例上 state中定义数据- 任意组件中
this.$store.state.xxx即可取值和改值;template中可以不用写this;可以通过计算属性简化编码 .js文件中导入store对象即可获取属性
vuex核心概念-state
state作用 : 储存公共数据 vuex 可以在任何页面使用 使用方法 : this.$store.state.xxx
- ./vuex/index.js 储存数据
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//1.state作用:存储数据
state: {
user:{
name:'ikun',
age:30
}
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
- home.vue 使用数据
- my.vue也可以使用vuex数据
<template>
<div>
<h1>首页</h1>
<button>点我修改vuex数据</button><br>
<button>点我发送ajax请求</button>
<div>
<h2>个人信息</h2>
<p>我的名字是:{{ $store.state.user.name }}</p>
<p>我的年龄是:{{ $store.state.user.age }}</p>
</div>
<div>
<h2>图书管理信息</h2>
<ul>
<li></li>
</ul>
</div>
</div>
</template>
<script>
export default {
name:'home',
}
</script>
<style scoped>
p{
color:red;
}
</style>
getters派生状态(计算属性)
语法如下
现在getters中声明一个计算属性
new Vuex.store({
// 省略其他...
getters: {
// state 就是上边定义的公共数据state
计算属性名: function(state) {
return 要返回的值
}
}
})
使用getter中的计算属性
- $store.getters.getter的名字
./vuex/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//1.state作用:存储数据
state: {
user:{
name:'ikun',
age:30
}
},
/* 2.2.getter作用:
官方术语:从state中派生状态(使用state中的数据,计算得出一些新数据)
说人话: 相当于state的计算属性
*/
getters: {
getInfo(state){
//state:就是vuex上面的state
return `我是${state.user.name},我今年${state.user.age}岁了`
}
},
//2.
mutations: {
},
actions: {
},
modules: {
}
})
home.vue :
<div>
<h2>个人信息</h2>
<p>我的名字是:{{ $store.state.user.name }}</p>
<p>我的年龄是:{{ $store.state.user.age }}</p>
<p>自我介绍:{{ $store.getters.getInfo }}</p>
</div>
vuex核心概念- Mutations
Mutation作用:更新state中的数据
既然可以直接通过this.$store.state来修改,为什么不能这么写呢?
原因: 在组件中直接state,我们的vue tools不会追踪数据的修改,这样不便于维护(不知道这个全局数据什么时候被修改了,再加上vuex是全局响应式的,一旦修改所有使用的地方全部修改。非常不便于维护)
Mutation语法如下:
- 分两个格式: 注册的格式,调用的格式
- 定义格式: 如下
- 每一项都是一个函数,可以声明两个形参:
- 第一个参数是必须的,表示当前的state。在使用时不需要传入
- 第二个参数是可选的,表示载荷,是可选的。在使用时要传入的数据
- 专业术语载荷:表示额外的参数
- 使用格式:this.$store.commit('mutation名', 载荷实参 )
- 这个事件名就是Mutation中的函数名。(类似于$emit的一种事件通知机制)
new Vue.store({
// 省略其他...
mutations:{
// 每一项都是一个函数,可以声明两个形参
mutation名1:function(state [, 载荷]) {
},
mutation名2:function(state [, 载荷]) {
},
}
})
- ./vuex/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//1.state作用:存储数据
state: {
user:{
name:'ikun',
age:30
}
},
/* 2.2.getter作用:
官方术语:从state中派生状态(使用state中的数据,计算得出一些新数据)
说人话: 相当于vuex的计算属性
*/
getters: {
getInfo(state){
//state:就是vuex上面的state
return `我是${state.user.name},我今年${state.user.age}岁了`
}
},
//3.mutations作用:修改state中的数据
mutations: {
setUser(state,newData){
state.user = newData
}
},
actions: {
},
modules: {
}
})
- home.vue
export default {
name:'home',
methods: {
doClick(){
this.$store.commit('setUser', {
name:'it李宗盛',
age:38
})
}
},
}
Vuex-mutaions拓展理解
问:为啥是$store.commit('mutations的名字')而不是$store.mutations的名字()?
答:Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler) 。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
问:数据不可以该在组件内部直接修改吗?
答:不能。虽然语法上不报错,也有响应式的特点。但是不推荐。特别是在严格模式下会报错。若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过 mutation的函数,vue就会报错
vuex辅助函数-mapState
官网文档:vuex辅助函数-mapState
mapState作用: 将vuex中的数据映射到组件的计算属性中
- 我们在组件中访问vuex数据,需要通过
this.$store.state.属性名,单词太常,写起来很麻烦。 -
-
- 通过mapState函数,可以在组件中直接通过
this.属性名来访问vuex中的数据
- 通过mapState函数,可以在组件中直接通过
-
mapState语法
- 在要使用的组件中导入mapState辅助函数:
import { mapState } from 'vuex' - 在这个组件的computeds中来映射计算属性
export default {
name: "my",
computed:{
//计算属性
//2.将vuex中的user映射成计算属性(与下面代码完全等价)
...mapState(['user'])
//计算属性:本质还是访问vuex中的数据
// user(){
// return this.$store.state.user
// }
}
};
...mapState( ['属性名a' , '属性名b'] )
这行代码相当于自动帮你生成一个对应的计算属性 属性名(){ return this.$store.state.属性名 }
vuex核心概念:actions
actions介绍
- actions与mutations相同点 :都是修改state数据
-
-
.actions与mutations不同点
-
mutations:同步更新
-
actions: 异步更新(例如你的数据来源于ajax)
-
- 为什么要有actions, 假如你有一个数据,需要通过ajax请求来获取。然后你想存入vuex,应该怎么做?
- 1.在组件的created钩子中发送ajax请求
- 2.服务器响应数据之后,调用$store.commit()提交给mutations更新(手动挡)
- 方案二:
- 1.直接在actions中发送ajax请求
- 2.actions会自动帮你把数据提交到mutations更新(自动挡)
actions语法如下
new Vuex.store({
// 省略其他...
actions: {
// context对象会自动传入,它与store实例具有相同的方法和属性
action的名字: function(context, 载荷) {
// 1. 发异步请求, 请求数据
// 2. commit调用mutation来修改数据
// context.commit('mutation名', 载荷)
}
}
})
在组件中通过this.$store.dispatch('actions的名字', 参数)来调用action
vuex核心概念modules
- modules作用:模块化处理vuex数据
- 当vuex中需要存储的数据很多的时候,就需要使用moudles进行模块化处理
- 一般开发中moudles使用不多哈。 只有那种特别复杂,庞大的项目才可能用到
使用modules语法如下
export default new Vuex.Store({
// state: 用来保存所有的公共数据
state: {},
getters: {},
mutations: {},
actions: {},
modules: {
模块名1: {
// namespaced为true,则在使用mutations时,就必须要加上模块名
namespaced: true,
state: {},
getters: {},
mutations: {},
actions: {},
modules: {}
},
模块名2: {
// namespaced不写,默认为false,则在使用mutations时,不需要加模块名
state: {},
getters: {},
mutations: {},
actions: {},
modules: {}
}
}
})
也可以把每一个modules单独写在一个js文件中,然后导入进来
访问数据和修改数据的调整
访问模块中的数据,要加上模块名
获取数据项: {{store.state.模块名.数据项名}} 获取getters: {{store.getters['模块名/getters名']}}
访问模块中的mutations/actions:
- 如果namespaced为true,则需要额外去补充模块名
- 如果namespaced为false,则不需要额外补充模块名
- $store.commit('mutations名') // namespaced为false
- $store.commit('模块名/mutations名') // namespaced为true