组件间的通信方式
约 1640 字大约 5 分钟
2025-03-13
1. prop属性 父传子
通过 prop 属性,可以实现父组件向子组件传递信息
父组件
<template>
<div>
<!-- 传递值 -->
<Test :obj="obj" info="测试"/>
</div>
</template>
<script>
import Test from "../components/Test.vue"; // 引入子组件
export default {
name: "about",
components: { Test }, // 注册子组件
data() {
return {
obj: {
code: 200,
title: "父组件传值title",
},
};
},
};
</script>
子组件
<template>
<div>
<h1>{{obj.code}}</h1><br>
<h2>{{obj.title}}</h2>
<h3>{{info}}</h3>
</div>
</template>
<script>
export default {
name:'test',
props:{
obj:Object,
info: [String,Number] //info值为其中一种类型即可,其他类型报警告
}
}
</script>
2. $emit事件 子传父
通过 $emit,可以实现子组件向父组件传递信息
父组件
<template>
<div>
<Test @return="loadData" /><!-- 传递值 -->
</div>
</template>
<script>
import Test from "../components/Test.vue"; // 引入子组件
export default {
name: "about",
components: { Test }, // 注册子组件
methods: {
loadData(param) {
console.log(param); // '子组件传递过来的值'
}
}
};
</script>
子组件
<script>
export default {
name: "Test",
created() {
this.$emit('return','子组件传递过来的值')
},
};
</script>
3. v-model 值绑定 双向获取
v-model
为双向传值,主要是通过两方面:prop和$emit来实现
父组件
<!-- xxData和子组件里的customValue的属性值可以不一样 -->
<Test v-model="xxData" info="测试"/>
子组件
<script>
export default {
name: "Test",
props: ['customValue'],
model: {
prop: 'customValue',
event: 'update'
},
created() {
this.$emit('update', newCustomValue) // 当值发生变化时,抛出事件触发更新
},
};
</script>
4. $refs 父获取子
通过该属性可以获取已经标记ref='xxx'
的子组件,通过this.$refs.xxx
来访问对应的属性和方法。
5. $children 父获取子
可以通过该属性获取子组件的集合(列表),根据下标 index 来获取想操作的子组件。
this.$children[index].xxxx;
6. $parent 子获取父
通过该属性可以访问父组件的属性和方法
this.$parent.getQuery();
this.$parent.xxxxx;
7. provide
和 inject
隔代注入 父传子 Vue3
实现父组件向子孙孙组件传值。(层级不限,跨越层级),父组件通过provide
提供信息,后代组件通过inject
注入该信息。
父组件
export default {
name: "father",
provide() { // 使用函数return主要是为了确保数据响应性 和组件解耦
return {
titleFather: "父组件的值",
};
},
};
子/孙组件
export default {
name: "sonone",
inject: ["titleFather"],
created() {
console.log(this.titleFather); // 父组件的值
},
};
8. $attrs 父传子
包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
9. $listeners 父传子
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
10. EventBus 事件总线 随便传
需要考虑组件加载的生命周期,缺点就是代码变复杂,维护困难
$emit
抛出事件,发送数据。 通常放在mounted
或用户交互的回调函数
中
$on
检测到对应事件,接收数据。通常放在mounted
钩子中
$off
页面销毁前,需要及时清理监听,否则会造成内存泄漏。通常放在beforeDestroy
钩子中解绑事件
发送数据
// ComponentB.vue
export default {
methods: {
sendData() {
this.$bus.$emit('xxx', { name: 'Vue', version: '3.x' });
}
}
}
接受数据数据
// ComponentA.vue
export default {
mounted() {
this.$bus.$on('xxx', this.demo);
},
methods: {
demo(data) {
console.log(data); // 处理接收到的数据
}
},
beforeDestroy() {
this.$bus.$off('xxx'); // 组件销毁前解绑事件
}
}
11. Vuex 随便传
State 仓库
State就是store仓库,用来存放取数据。mapState是为了简化代码,一次性获取多个store里的数据
// 获取单个数据
<template>
<div>{{ count }}</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
}
}
</script>
// 映射多个数据
<script>
import { mapState } from 'vuex'
export default {
computed: mapState({
count: state => state.count,// 箭头函数可使代码更简练
countAlias: 'count',// 字符串参数'count' 等同于 `state => state.count`
countPlusLocalState (state) {
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
return state.count + this.localCount
}
})
// 如果不需要别名,可以用数组形式
computed: mapState([
'count'// 映射 this.count 为 store.state.count
])
}
</script>
Getter 获取数据,加工数据
Getter是相当于对state里的数据的一个加工处理,拿到的返回值就是处理后的值,但不允许在getter里取改变store里的值。
Mutation 突变 数据刷新
Mutation是同步执行的,不能出现异步任务,比如promise。触发Mutation后,store里的值会立即刷新。Moutation的变化是可以被devtool追踪到的。
你可以在组件中使用 this.$store.commit('xxx')
提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 和 mutation关联(需要在根节点注入 store)。
Action 动作 方法
Action支持异步任务,相当于为了弥补Mutation不能执行异步任务的遗憾,使其搭配异步任务完成某一个Action。同时Action也是相当于把某些高频出现的包含业务逻辑的methods提取出来,作为一个公共的Aciton使用。
可以在组件中使用this.$store.dispatch('xxx')
分发 action,或者使用 mapActions 辅助函数将组件的 methods 关联到Action调用(需要先在根节点注入 store):
this.$store.dispatch('products/getAllProducts', xxxxx)
Modules 模块
项目比较大,逻辑比较复杂的时候,sotre、action、mutation等相关代码会变得非常庞大。进行模块拆分,有利于提高代码的维护性和可靠性
与表单的有机结合
如果我们直接把vuex里的值绑定到的表单的v-model上。因为v-model是双向刷新的,而vuex不允许直接修改值来刷新。所以我们需要使用另外一个变量,设置为计算属性(computed)。通过该属性的get方法来取出vuex里存储的对应值,通过set来提交Mutation刷新Vuex里的值。如果需要设置该值的初始值,可以初始化的时候赋初始值。
<input v-model="message">
// -------
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
vue3响应式原理
二者的不同
更新日志
e7112
-1于