- A+
所属分类:Web前端
VUE组件之间通信的方式有哪些(SSS)
常见使用场景可以分为三类:
-
父子通信:
- null
父向子传递数据是通过props
,子向父是通过$emit / $on
$emit / $bus
Vuex
- 通过父链 / 子链也可以通信(
$parent
/$children
) ref
也可以访问组件实例
- null
-
兄弟通信:
$emit / $bus
Vuex
-
跨级通信:
$emit / $bus
;Vuex
;provide / inject API
$attrs/$listeners
$emit / $bus
// main.js Vue.prototype.$bus = new Vue() // event Bus 用于无关系组件间的通信。
A触发B
// A this.$bus.$emit('new-messsage-at-me', { data: { conversationID: message.conversationID } })
// B mounted() { this.$bus.$on('new-messsage-at-me', event => { if ( event.data.conversationID === this.conversation.conversationID && this.conversation.conversationID !== this.currentConversation.conversationID ) { this.hasMessageAtMe = true } }) },
父子组件通信
- 父组件向子组件传值( props ):
//App.vue父组件 <template> <div id="app"> <users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名 </div> </template> <script> import Users from "./components/Users" export default { name: 'App', data(){ return{ users:["Henry","Bucky","Emily"] } }, components:{ "users":Users } }
//users子组件 // 注:组件中的数据共有三种形式:data、props、computed <template> <div class="hello"> <ul> <li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面 </ul> </div> </template> <script> export default { name: 'HelloWorld', props:{ users:{ //这个就是父组件中子标签自定义名字 type:Array, required:true } } } </script>
- 子组件向父组件传值(B 组件中 $emit, A 组件中 v-on ):
// 子组件 <template> <header> <h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件 </header> </template> <script> export default { name: 'app-header', data() { return { title:"Vue.js Demo" } }, methods:{ changeTitle() { this.$emit("titleChanged","子向父组件传值");//自定义事件 传递值“子向父组件传值” } } } </script>
// 父组件 <template> <div id="app"> <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致 // updateTitle($event)接受传递过来的文字 <h2>{{title}}</h2> </div> </template> <script> import Header from "./components/Header" export default { name: 'App', data(){ return{ title:"传递的是一个值" } }, methods:{ updateTitle(e){ //声明这个函数 this.title = e; } }, components:{ "app-header":Header, } } </script>
$ref 与 $parent $children
- 使用 this.$parent查找当前组件的父组件。
- 使用 this.$children查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的。
- 使用 this.$root查找根组件,并可以配合$children遍历全部组件。
- 使用 this.$refs查找命名子组件(
)( this.$refs.one )
$attrs / $listeners
- 两者的出现使得组件之间跨组件的通信在不依赖 vuex 和事件总线的情况下变得简洁,业务清晰。
- A->B->C 多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点杀鸡用牛刀。Vue 2.4 版本提供了另一种方法,使用 v-bind=”$attrs”, 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用。
- 简单来说:$attrs 与 $listeners 是两个「对象」,$attrs 里存放的是父组件中绑定的非 Props 属性, 唯一缺点 没在props定义的属性 会显示在生成的html标签上, 解决办法:通过inheritAttrs:false,避免顶层容器继承属性; $listeners里存放的是父组件中绑定的非原生事件。
A父组件
<template> <div> <child-dom :foo="foo" :coo="coo" v-on:upRocket="reciveRocket" > </child-dom> </div> </template> <script> import childDom from "@/components/ChildDom.vue"; export default { name:'demoNo', data() { return { foo:"Hello, world", coo:"Hello,rui" } }, components:{childDom}, methods:{ reciveRocket(){ console.log("reciveRocket success") } } } </script>
B子组件
<template> <div> <p>foo:{{foo}}</p> <p>attrs:{{$attrs}}</p> <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild> </div> </template> <script> import childDomChild from './childDomChild'; export default { name:'child-dom' props:["foo"], inheritAttrs:false, } </script>
C子组件的子组件
<template> <div> <p>coo:{{coo}}</p> <button @click="startUpRocket">我要发射火箭</button> </div> </template> <script> export default { name:'childDomChild', props:['coo'], methods:{ startUpRocket(){ this.$emit("upRocket"); console.log("startUpRocket") } } } </script>
provide / inject
- 适用于 隔代组件通信 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
- 如果是单一的只是拿数据使用,在父组件定义,则在所有子组件都能为之所用
- 官网不建议在应用中直接使用该办法,理由很直接:他怕你"管不好"
1.一般情况使用都是在app.vue配置为:
provide () { return { isTest: this } },
2.所有子组件都可以引用 拿到app.vue里面的所有数据
inject: ['isTest'],
欢迎留言~~~