“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情”
解决组件通信的方法有哪些?
| 序号 | 组件关系 | 数据通信 |
|---|---|---|
| 1 | 父子关系 | 子传父:$emit ; 父传子:props |
| 2 | 非父子关系 | eventBus: emit |
| 3 | 非父子关系 | vuex |
1.Vuex介绍
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex的数据状态管理:管理数据,并且管理数据的状态
vuex作用:实现所有组件间的数据共享
1.vuex的作用是解决多组件状态共享的问题,在大型的项目中,组件通讯会变得很混乱,使用vuex可以统一管理组件之间的通讯
- 它是
独立于组件而单独存在的,所有的组件都可以把它当作一座桥梁来进行通讯。
2.使用vuex好处
响应式: 只要vuex中的数据变化,对应的组件会自动更新(类似于vue数据驱动)- 操作更简洁 : 类似于sessionStorage,只有几个方法
2.Vuex使用场景
实际开发中,组件传值大多数情况下还是使用
父子组件传值少部分情况下会用vuex. (数据需要在非常多的页面使用,比如用户头像,好几个页面都要显示那种)
-
1.不是所有的场景都适用于vuex,只有在必要的时候才使用vuex,如果
不必要,尽量别用- 使用了vuex之后,会一定程度上增加了项目的复杂度
-
2.适合使用vuex场景
-
这个数据需要在
很多个地方使用,如果采用组件传值方式,写起来很麻烦,而且多个地方都要写- 例如:用户信息(姓名,头像),可能会在很多个地方使用(个人页面,评论页面等)
-
-
3.不适合使用vuex场景
- 这个数据
不需要多个地方使用,如果某个数据仅仅只是在两个组件之间通讯,优先使用props或$emit
- 这个数据
-
4.vuex特点
- (1)所有组件数据共享
- (2)响应式: 一旦vuex数据修改,所有使用的地方都会自动更新
3.在Vue脚手架创建vuex
3.1使用vue ui创建创建
直接勾选vuex,会自动帮我们完成配置
3.2如果创建是没有选择vuex,可以手动添加
在项目根目录执行
vue add vuex
3.3Vuex的store文件夹
在执行以上的两个命令之中的任何一个后,
会在src文件夹生成一个store文件夹,默认含有一个index.js文件
index.js内容如下
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
//1.state作用:存储数据
state: {
},
/* 2.2.getter作用:
官方术语:从state中派生状态(使用state中的数据,计算得出一些新数据)
*/
getters: {},
//3.mutations作用:修改state中的数据
mutations: {
},
//4.action作用: 异步更新数据
actions: {},
//5.module作用:模块化处理vuex数据
modules: {}
});
4.vuex核心概念-state
4.1.state作用:存储数据
//1.state作用:存储数据
state: {
user: {
name: "阿斯蒂芬",
age: 34
}
},
组件中获取数据方法
<p>我的名字是:{{ $store.state.user.name }}</p>
<p>我的年龄是:{{ $store.state.user.age }}</p>
4.2mapState 辅助函数
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用
mapState辅助函数帮助我们生成计算属性,让你少按几次键 在组件中使用mapstate
上面是vuex官方文档,什么意思呢?通俗的讲就是
我们通过计算属性把store.state属性平铺到组件中的时候,
属性较多时,每个属性都要写一次,computed要写好多次,
使用mapstate只用写一行代码具体使用方法如下:
- 先导入辅助函数mapstate:
import { mapState } from 'vuex' - 展开运算符和mapstate组合使用:
...mapState(['user'])
<script>
//导入辅助函数mapState
import { mapState } from 'vuex'
export default {
name: "my",
computed: {
//计算属性
//2.将vuex中的user映射成计算属性(与下面代码完全等价)
...mapState(['user'])
// 等价于自动帮我们生成以下代码
//计算属性:本质还是访问vuex中的数据
// user(){
// return this.$store.state.user
// }
},
};
</script>
5.vuex核心概念-getters
getter是state的派生属性
相当于计算属性computed的get(){},
在页面加载时会计算一次,存入内存,此外数据没有变化,则不会执行,而是直接用内存中的数据,减少了计算次数,降低性能消耗
语法如下:
getter的第一个参数是:state
getter 可以选择其他的getter作为第二个参数
getters: {
// ...
doneTodosCount (state, getters) {
return getters.doneTodos.length
}
}
6.vuex核心概念 Mutations
特点:同步更新数据
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
6.1声明mutations
- mutations函数最多只能传两个参数,state是默认参数,payload是额外参数(载荷)
(1)声明mutations
mutations: {
mutation名(state,payload){
//修改state数据
}}
6.2组件中使用mutations
- commit(type:'mutation名',payload)
只能传两个参数,type:"mutation名"是默认参数,payload是额外参数(载荷),- 如果一定要传俩个参数,可以吧参数包在对象中作为payload载荷
doClick() {
this.$store.commit("mutation名",payload);
},
6.3 为什么一定要加一个commit才能调用mutations的方法?
- 因为Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler) 。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
7.vuex核心概念 actions
异步更新state数据,通过motations间接更新数据
7.0 action传值流程详细图解
7.1组件中使用dispatch更新
- 提交action更新:载荷一般为ajax参数
this.$store.dispatch('action名',载荷)- 任意组件:触发actions this.$store.dispatch('action名',载荷)
doActions(){
this.$store.dispatch('getList',{num:10})
}
7.2声明actions,actions发送异步请求
(1)声明actions
action名(context,payload){
//context:vuex实例对象
//payload:载荷(一般是ajax参数)
}
-
context是vuex中的所有对象:state,getters等
-
payload是传过来的参数
actions: {
async getList(context, payload) {
// context是vuex中的所有对象:state,getters等
// payload是传过来的参数
const { data: res } = await axios.get("https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books")
context.commit('updateList', res.data)
}
},
7.3提交mutation更新
mutations: {
updateList(state, payload) {
state.list = payload
}
},
7.4更新state
state: {
list: []
},
8.vuex核心概念 Module
当vuex中需要存储的数据很多的时候,就需要使用moudles进行模块化处理
- 一般实际开发中moudles使用不多。 只有复杂,庞大的项目才可能用到
8.1使用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文件中,然后导入进来
8.2组件中访问Vuex模块数据
访问模块中的数据,要加上模块名
获取数据项: {{$store.state.模块名.数据项名}}
获取getters: {{$store.getters['模块名/getters名']}}
访问模块中的mutations/actions:
- 如果namespaced为true,则需要额外去补充模块名
- 如果namespaced为false,则不需要额外补充模块名
$store.commit('mutations名') // namespaced为false
$store.commit('模块名/mutations名') // namespaced为true