组件交互(传值,交互)分类:
父组件 => 子组件:
属性props
// child
props: { msg: String }
// parent
<HelloWorld msg="Welcome to Your Vue.js App"/>
引用refs
// parent
<HelloWorld ref="hw" />
this.$refs.hw.xx
子组件 => 父组件:自定义事件
// child
this.$emit('add', good)
// parent
<Cart @add="cartAdd($event)"></Cart>
兄弟组件:通过共同祖辈组件
通过共同的祖辈组件搭桥,$parent或$root。
// brother1
this.$parent.$on('foo', handle)
// brother2
this.$parent.$emit('foo')
祖先和后代之间
provide/inject:能够实现祖先给后代传值
// ancestor
provide() {
return {foo: 'foo'}
}
// descendant
inject: ['foo']
dispatch:后代给祖先传值
// 定义一个dispatch方法,指定要派发事件名称和数据
function dispatch(eventName, data) {
let parent = this.$parent
// 只要还存在父元素就继续往上查找
while (parent) {
// 父元素用$emit触发
parent.$emit(eventName,data)
// 递归查找父元素
parent = parent.$parent
}
}
// 使用,HelloWorld.vue
<h1 @click="dispatch('hello', 'hello,world')">{{ msg }}</h1>
// App.vue
this.$on('hello', this.sayHello)
任意两个组件之间:事件总线 或 vuex
事件总线:创建一个Bus类负责事件派发、监听和回调管理
// Bus:事件派发、监听和回调管理
class Bus{
constructor(){
// {
// eventName1:[fn1,fn2],
// eventName2:[fn3,fn4],
// } this.callbacks = {}
}
$on(name, fn){
this.callbacks[name] = this.callbacks[name] || [] this.callbacks[name].push(fn)
}
$emit(name, args){
if(this.callbacks[name]){
this.callbacks[name].forEach(cb => cb(args))
}
}
}
// main.js
Vue.prototype.$bus = new Bus()
// child1
this.$bus.$on('foo', handle)
// child2
this.$bus.$emit('foo')
vuex:创建唯一的全局数据管理者store,通过它管理数据并通知组件状态变更
直接上案例,看效果:
GrandGrandChild.vue组件:
<template>
<div>
<h2>GrandGrandson1</h2>
<p>祖先元素提供的数据 : {{woniu}}</p>
<button @click="$dispatch('dispatch','哈喽 我是GrandGrandChild1')">dispatch</button>
<h3>{{msg}}</h3>
</div>
</template>
<script>
export default {
name:'GrandGrandChild1',
inject: ["woniu"],
data() {
return {
msg: ""
};
},
mounted(){
this.$on("boardcast",msg=>{
this.msg = '接收boardcast消息:'+ msg
})
this.$bus.$on("event-bus",msg=>{
this.msg = '接收event-bus消息:'+ msg
})
},
};
</script>
GrandChild1.vue组件:
<template>
<div>
<h2>Grandson1</h2>
<p>祖先元素提供的数据 : {{woniu}}</p>
<h3>{{msg}}</h3>
</div>
</template>
<script>
export default {
name: "GrandChild1",
data() {
return {
msg: ""
};
},
inject: ["woniu"],
mounted() {
this.$on("dispatch", msg => {
this.msg = "接收dispatch消息:" + msg;
});
this.$on("boardcast", msg => {
this.msg = "接收boardcast消息:" + msg;
});
this.$bus.$on("event-bus", msg => {
this.msg = "接收event-bus消息:" + msg;
});
}
};
</script>
GrandChild2.vue组件:
<template>
<div>
<h2>Grandson2</h2>
<p>
祖先元素提供的数据 : {{woniu}}
</p>
<button @click="eventBus">$bus发布</button>
<h3>{{msg}}</h3>
<grand-grand-child1>
</grand-grand-child1>
</div>
</template>
<script>
import GrandGrandChild1 from '@/components/communicate/GrandGrandChild1'
export default {
name:'GrandChild2',
components:{GrandGrandChild1},
inject:['woniu'],
data(){
return {
msg:""
}
},
methods:{
eventBus(){
this.$bus.$emit('event-bus','测试eventBus')
}
},
mounted(){
this.$on("dispatch",msg=>{
this.msg = '接收dispatch消息:'+ msg
})
this.$on("boardcast",msg=>{
this.msg = '接收boardcast消息:'+ msg
})
}
}
</script>
Child1.vue组件:
<template>
<div>
<h2>Child1</h2>
<p>{{title}}</p>
<h3>{{msg}}</h3>
<button @click="toParent">传递到父元素</button>
<button @click="$boardcast('boardcast','我是Child1')">广播子元素</button>
<grand-child1></grand-child1>
<grand-child2></grand-child2>
</div>
</template>
<script>
import GrandChild1 from "@/components/communicate/GrandChild1";
import GrandChild2 from "@/components/communicate/GrandChild2";
export default {
name: "Child1",
props: ["title"],
data() {
return {
msg: ""
};
},
components: {
GrandChild1,
GrandChild2
},
methods: {
toParent() {
this.$emit("getmsg", "爸爸,我知道错了");
}
},
mounted() {
this.$on("dispatch", msg => {
this.msg = "接收dispatch消息:" + msg;
});
this.$bus.$on("event-bus",msg=>{
this.msg = '接收event-bus消息:'+ msg
})
}
};
</script>
Child2.vue组件:
<template>
<div>
<h2>Child2</h2>
<h3>{{msg}}</h3>
<grand-child1>
</grand-child1>
</div>
</template>
<script>
import GrandChild1 from '@/components/communicate/GrandChild1'
export default {
name:'Child2',
props:['title'],
data(){
return {
msg:""
}
},
components:{
GrandChild1,
},
methods:{
toParent(){
this.$emit('getmsg','爸爸,我知道错了')
}
},
mounted(){
this.$on("dispatch",msg=>{
this.msg = '接收dispatch消息:'+ msg
})
}
}
</script>
Index.vue组件:
<template>
<div id="app">
<h2>Parent</h2>
<h3>{{msg}}</h3>
<child1 :title="title1" @getmsg="getmsg"></child1>
<child2></child2>
</div>
</template>
<script>
import Child1 from "@/components/communicate/Child1";
import Child2 from "@/components/communicate/Child2";
export default {
name: "app",
provide: {
woniu: "我是爷爷"
},
data() {
return {
msg: "",
title1: "我是你爸爸"
};
},
methods: {
getmsg(msg) {
this.msg = msg;
}
},
components: { Child1, Child2 },
mounted() {
this.$on("dispatch", msg => {
this.msg = "接收dispatch消息:" + msg;
});
this.$bus.$on("event-bus", msg => {
this.msg = "接收event-bus消息:" + msg;
});
}
};
</script>
<style scoped>
div {
border: 3px blue solid;
padding: 10px;
display: inline-block;
vertical-align: top;
/* width:50%; */
}
h1,
h2 {
font-size: 18px;
margin: 5px 0;
}
h3 {
color: red;
font-size: 14px;
}
</style>