$emit:向父级传值
单纯从emit角度而言没啥好说的
组件内部$emit('someEvent')
使用组件时:<SomeComponent @someEvent="functionToHandleSomeEvnent">
,注意这里不传参,someEvent需保持一致
son组件
<template>
<div class="son">
<h1>这是son组件</h1>
<span>来自father的值(fatherToSon1):{{fatherToSon1}}
<button @click="changeFatherToSon1">使用emit</button>
</span>
</div>
</template>
<script>
export default {
name: "Son",
data(){
return {
sonData:1
}
},
props: {
fatherToSon1: Number,
},
methods: {
changeFatherToSon1() {
this.$emit('changeFatherToSon1',2)
}
}
}
</script>
father组件
在使用son组件的地方注册一个和son组件中emit第一个参数一样名字的函数,简单来说,就是son组件emit时的第一个参数要和使用son组件时@后面写的保持一致。(@可以理解为给某一个类型的事件绑定一个处理函数@事件类型=处理该事件的函数
,像@click
是vue帮我们定义好的,而@changeFatherToSon1
是我们自己定义的)
<template>
<div class="father">
<h1>这是father组件</h1>
<p>来自ancestors的值:{{provideFromAncestors}}</p>
<button @click="showRef">$ref访问子组件</button>
<Son ref="son":fatherToSon1="fatherToSon1" @changeFatherToSon1="changeFatherToSon1"/>
<Son/>
<br>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
components: {
Son
},
data() {
return {
fatherToSon1: 1,
}
},
methods: {
changeFatherToSon1(value) {
this.fatherToSon1 = value
},
}
}
</script>
$emit相关变种
1、$emit('update:value',someValue)
son组件
<template>
<div class="son">
<h1>这是son组件</h1>
<span>
来自father的值(fatherToSon2):{{fatherToSon2}}
<button @click="changeFatherToSon2">使用update:value+@update:value</button>
</span>
</div>
</template>
<script>
export default {
name: "Son",
data(){
return {
sonData:1
}
},
props: {
fatherToSon2: Number
},
methods: {
changeFatherToSon2() {
this.$emit('update:value1',20)
},
}
}
</script>
father组件
<template>
<div class="father">
<h1>这是father组件</h1>
<Son ref="son" :fatherToSon2="fatherToSon2" @update:value1="value=>{this.fatherToSon2=value}"
/>
<Son/>
<br>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
components: {
Son
},
data() {
return {
fatherToSon2: 10,
}
},
}
</script>
这里value=>{this.fatherToSon2=value}
也可以单独抽出一个函数。
父组件还有一种语法糖的写法
<template>
<div class="father">
<h1>这是father组件</h1>
<Son ref="son" :fatherToSon2="fatherToSon2" :value2.sync="fatherToSon2"
/>
<Son/>
<br>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
components: {
Son
},
data() {
return {
fatherToSon2: 10,
}
},
}
</script>
@update:value1="value=>{this.fatherToSon2=value}"
改为:value2.sync="fatherToSon2"
即可
2、$emit('input')
注意,input事件是vue帮我们定义好的,我们通过emit来触发,以达到通信的目的,其实和正常的$emit发射自定义事件是差不多的
son组件
<template>
<div class="son">
<h1>这是son组件</h1>
<span>
来自father的值(fatherToSon5):{{fatherToSon5}}
<button @click="changeFatherToSon5">emit('input')+@input</button>
</span>
</div>
</template>
<script>
export default {
name: "Son",
data(){
return {
sonData:1
}
},
props: {
fatherToSon5: Number,
},
methods: {
changeFatherToSon5(){
this.$emit('input',20000)
},
}
}
</script>
<style scoped>
.son {
background-color: darkgray;
color: white;
}
</style>
Father组件
<template>
<div class="father">
<h1>这是father组件</h1>
<Son ref="son"
:fatherToSon5="fatherToSon5" @input="value=>{this.fatherToSon5=value}"
/>
<Son/>
<br>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
components: {
Son
},
data() {
return {
fatherToSon5: 10000
}
},
}
</script>
这里其实也有个语法糖叫v-model,v-model其实可以理解为:value="somevalue" @input="value=>this.somevalue=value"
的简写形式,当我们把这个v-model挂到组件上时,就可以形成一种新的组件通信方法。
其中子组件不需要改动,父组件修改
<template>
<div class="father">
<h1>这是father组件</h1>
<Son ref="son"
v-model="fatherToSon5"
/>
<Son/>
<br>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
components: {
Son
},
data() {
return {
fatherToSon5: 10000
}
},
}
</script>
emit相关的到这里就结束了
$root和$parent
这里和$children和$refs类似,$parent取当前组件实例的父组件实例,而$root取到根节点的组件,往往是app组件
$parent:向上派发事件
此处需要结合$emit一起食用
emit往往用于子组件通知父组件更新某个父组件的值,但是当组件层级达到三层即(son-father-grandpa)时,需要在son中使用$parent.$emit进行事件发射如果层级更深显然不可能无限$parent,于是我们需要让子组件调用$eventDispatch,让这个子组件向上的每一级父组件都进行$emit,一旦调用emit的组件的父组件监听了对应的事件,那么就会执行。
Vue.prototype.$eventDispatch = function (event, value) {
let parent = this.$parent
while (parent) {
parent.$emit(event, value)
parent = parent.$parent
}
}
举例:我们在ancestors上监听了emitToUpper
事件
<template>
<div class="ancestors">
<h1>这是祖先组件</h1>
<grand-pa @emitToUpper="dispatchToAncester"/>
</div>
</template>
<script>
import GrandPa from './GrandPa'
export default {
name: "Ancestors",
components:{
GrandPa
},
methods:{
dispatchToAncester(value){
console.log(`ancestors监听到了一个事件,值为${value}`);
},
}
}
</script>
<style scoped>
</style>
同样的,在app组件也可以进行监听emitToUpper
事件
<template>
<Ancestors @emitToUpper="dispatchToApp"/>
</template>
<script>
import Ancestors from '@/components/Ancestors'
export default {
name: 'App',
components: {
Ancestors
},
methods:{
dispatchToApp(value){
console.log(`app监听到了一个事件,值为${value}`);
}
}
}
</script>
<style>
</style>
只要监听了@emitToUpper事件的组件都会触发对应的函数
<template>
<div class="son">
<h1>这是son组件</h1>
<button @click="emitToUpper">使用$eventDispatch发射事件</button>
</div>
</template>
<script>
export default {
name: "Son",
methods: {
emitToUpper(){
this.$eventDispatch('emitToUpper','aaaa')
},
}
}
</script>
<style scoped>
</style>