Vue组件间通讯方法总结
目录1. props
-
使用方法:父组件在调用子组件时,在标签内绑定需要传输的数值,随后子组件在props内接收并使用
-
传递方向:父组件 → 子组件
-
注意事项:子组件通过props接收到数据后,不能直接修改父组件的数据
-
示例代码
- 父组件
<template> <div> <List-item :arr="arr"></List-item> </div> </template> <script> import ListItem from "./ListItem"; export default { data() { return { str: "给子组件传值", } }, components: { ListItem } } </script>
- 子组件
<template> <div>{{msg}}</div> </template> <script> export default { props: { msg: String, } } </script>
2. $emit
和$on
-
使用方法:在确定父组件需要子组件中的值后,父组件通过
v-on
或$on
绑定一个自定义事件到子组件,子组件使用$emit
发送同名自定义事件到父组件,父组件接收该事件并调用事件中的参数data以获取子组件中的值 -
传递方向:子组件 → 父组件
-
示例代码
- 父组件
<template> <div> <!-- 监听自定义事件 --> <List-item v-on:welcome="getWelcome"></List-item> </div> </template> <script> import ListItem from "./List-item"; export default { components: { ListItem }, methods: { getWelcome(data) { alert(data) } } } </script>
- 子组件
<template> <button @click="handleClick">Click me</button> </template> <script> export default { methods: { handleClick() { // 使用 $emit 发送自定义事件 welcome this.$emit('welcome', '被传递的值'); } } } </script>
3. $refs
-
使用方法:在父组件中给子组件标签绑定一个ref属性,需要调用的时候直接
this.$refs
获取子组件中的数据 -
传递方向:子组件 → 父组件
-
注意事项:如果ref绑定在v-for的节点上,那么将获取到一个数组
-
示例代码
- 父组件
<template> <div> <List-item ref="item" :title="title"></List-item> <div>{{data}}</div> </div> </template> <script> import ListItem from "./List-item"; export default { data() { return { title: "我是title", data: "" } }, components: { ListItem }, mounted() { this.data = this.$refs.item.message; } } </script>
4. $attrs
和$listeners
-
使用方法:祖先组件把要传递的值绑定在子组件标签上。子组件不使用props接收,转而用同样的操作,使用
v-bind="$attrs"
将祖先组件的值绑定在孙子组件标签上,继续传递给孙子组件。以此类推层层传递 -
传递方向:祖先组件 → 孙子组件
-
注意事项:
$attrs
和$listeners
一般用于多层嵌套组件传递数据,而且不用中间处理的情况- 如果给子组件传递的数据,子组件不使用props接收,那么这些数据将作为组件的HTML元素的特性,绑定在
$attrs
上 $listeners
包含父作用域里 .native 除外的监听事件集合
-
示例代码
- 祖先组件
<template> <child :name="name" title="1111" ></child> </template> <script> export default{ data(){ return { name:"小解" } } } </script>
- 孙子组件
<template> <!--继续传给孙子组件--> <sun-child v-bind="$attrs"></sun-child> </template> <script> export default{ props:["name"], mounted(){ //props已经接收了name,此处attrs只剩下{title:1111} console.log(this.$attrs) } } </script>
5. provide和inject
-
使用方法:祖先组件中使用provide设置要传递的值,孙子组件中使用inject注入(接收)指定的值
-
传递方向:祖先组件 → 孙子组件
-
注意事项:
- 该传值方法常见于插件或者组件库里,顶层组件provide提供变量,后代组件通过inject来注入变量
- 传递的数据不是响应式的。inject接收到数据后,若provide中的数据改变,后代组件中的数据不会改变。建议只通过该方式传递对象或常量
-
示例代码
- 祖先组件
export default { name: "father", provide() { return { foo: 'hello' } }, }
- 孙子组件
export default { inject:['foo'], }
6. Vuex
-
传递方向:无限制
7. eventBus
-
使用方法:在公用区域挂载一个Bus,子组件如果需要向外部发送自定义事件就使用
Bus.$emit
,如果需要从外部接收自定义事件就使用Bus.$on
-
传递方向:无限制
-
注意事项:注意需要$off来取消监听,否则可能会造成内存泄漏
-
示例代码
- Bus的挂载
//方法一:抽离成一个单独的js文件,在需要时再引入 import Vue from "vue" export default new Vue() //方法二:直接挂载到全局 import Vue from "vue" Vue.prototype.$bus = new Vue() //方法三:注入到Vue根对象上 import Vue from "vue" new Vue()({ el:'#app'; data:{ Bus: new Vue() } })
- 子组件发送自定义事件到Bus
//import Bus from "./Bus.js" //(如果用的是方法一要加这一行) export default{ methods:{ handlerClick(){ //sendMsg是自定义事件名 Bus.$emit("sendMsg","向外部发送的数据") } } }
- 子组件从Bus接收自定义事件
//import Bus from "./Bus.js" //(如果用的是方法一要加这一行) export default{ mounted(){ //绑定监听事件 Bus.$on("sendMsg",data => { console.log("接收到数据:",data) }) }, beforeDestroy(){ //取消监听 Bus.$off("sendMsg") } }
8. $parent
, $children
, $root
-
注意事项:该通信方法维护困难,不推荐使用,仅作了解
-
使用方法:直接在需要通信的组件上调用以上三个属性
-
传递方向:
$children
:父组件 → 子组件$parent
:子组件 → 父组件$children
+$parent
:兄弟组件 → 兄弟组件- $root:根组件 → 子组件
-
示例代码
- 以父组件为中介实现兄弟组件间通讯
//子组件一 this.$parent.$on('confirm',handleConfirm) //子组件二 this.$patent.$emit('confirm',list)
- 获取子组件中数据
console.log(this.$children[0].msg)
- 调用根组件中方法
this.$root.handleRoot()