VUE 组件之间通信的形式有哪些(SSS)
常见应用场景能够分为三类:
-
父子通信:
- null
父向子传递数据是通过 props
,子向父是通过 $emit / $on
* `$emit / $bus`
* `Vuex`
* 通过父链 / 子链也能够通信(`$parent` / `$children`)* `ref` 也能够拜访组件实例
-
兄弟通信:
$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 查找命名子组件(<firstchild ref=”one”></firstchild>)(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'],
欢送留言~~~