小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
对上一篇文章:juejin.cn/post/701211… 子组件点击事件 在父组件接收的进行补充!
- 孙组件怎样发送事件给父组件监听到呢?
$attrs
- attrs, 可以使代码更加美观,更加简洁,维护代码的时候更方便。如果使用普通的父子组件传参prop和on会很繁琐;如果使用vuex会大材小用,只是在这几个组件中使用,没必要使用vuex;使用事件总线eventBus,使用不恰当的话,有可能会出现事件多次执行。 如果给组件传递的数据,组件不使用props接收,那么这些数据将作为组件的HTML元素的特性,这些特性绑定在组件的HTML根元素上
inheritAttrs
- inheritAttrs: false的含义是不希望本组件的根元素继承父组件的attribute,同时父组件传过来的属性(没有被子组件的props接收的属性),也不会显示在子组件的dom元素上,但是在组件里可以通过其$attrs可以获取到没有使用的注册属性, inheritAttrs: false是不会影响 style 和 class 的绑定
在很多开发情况下,我们只是想把A组件的信息传递给C组件,如果使用props 绑定来进行信息的传递,虽然能够实现,但是代码并不美观。
- 父组件:
<template>
<div>
<childDom :foo="foo" :zoo="zoo"> </childDom>
</div>
</template>
<script>
import childDom from '../../components/childDom';
export default {
name: "userProfileindex",
components:{childDom},
data() {
return {
foo: "Hello, foo",
zoo: "Hello, zoo"
};
}
};
</script>
- 子组件:
<template>
<div>
<p>foo:{{foo}}</p>
</div>
</template>
<script>
export default {
name:'childDom',
props:["foo"]
}
</script>
- 当显示父组件时,查看Dom结构,结构如下
给子组件关联数据,子组件如果不用props接收,那么这些数据就作为普通的HTML特性应用在子组件的根元素上
-
在2.4中新增选项inheritAttrs inheritAttrs的默认值为true, 将inheritAttrs的值设为false, 这些默认的行为会禁止掉。但是通过实例属性 $attrs ,可以将这些特性生效,且可以通过v-bind 绑定到子组件的非根元素上。
-
修改子组件代码如下:
<template>
<div class="child">
<span>子组件:</span>
<p>foo:{{foo}}</p>
<p>attrs:{{$attrs}}</p>
<childDomChild v-bind="$attrs"></childDomChild>
</div>
</template>
<script>
import childDomChild from '../childDomChild/index.vue';
export default {
name:'child-dom',
components: {
childDomChild
},
props:["foo"],
inheritAttrs:false,
}
</script>
<style scoped>
.child{
color: rgb(223, 177, 26);
border: 4px solid slateblue;
margin: 16px;
}
</style>
- 新增子组件 childDomChild
<template>
<div class="son">
<span>孙组件:</span>
<p>zoo:{{zoo}}</p>
</div>
</template>
<script>
export default {
name:'childDomChild',
props:["zoo"],
inheritAttrs:false
}
</script>
<style scoped>
.son{
margin: 16px;
color: tomato;
border:3px solid violet;
}
</style>
- 输出的结果如下: 从上面的代码,可以看出使用$attrs ,inheritAttrs 属性 能够使用简洁的代码,将A组件的数据传递给C组件 , 该场景的使用范围还是挺广的。
此时我们又想到了一个问题,c组件的信息,怎么同步给a组件呢? 用到了“$listeners”
vue2.4版本新增了listeners”, 在父(A)组件中,监听孙组件触发的事件。就能把孙(C)组件发出的数据,传递给父(A)组件。
父组件代码更新如下:
<template>
<div class="father">
<span>父组件:</span>
<childDom :foo="foo" :zoo="zoo" v-on:upRocket="reciveRocket"> </childDom>
</div>
</template>
<script>
import childDom from '../../components/childDom';
export default {
name: "userProfileindex",
components:{childDom},
data() {
return {
foo: "Hello, foo",
zoo: "Hello, zoo"
};
},
methods:{
reciveRocket(res){
console.log("接收到来自孙组件的click事件",res)
}
}
};
</script>
<style scoped>
.father{
color: rgb(31, 32, 32);
border: 2px solid springgreen;
}
</style>
- 子组件更新如下: 孙组件加上v-on="$listeners
<template>
<div class="child">
<span>子组件:</span>
<p>foo:{{foo}}</p>
<p>attrs:{{$attrs}}</p>
<childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild>
</div>
</template>
<script>
import childDomChild from '../childDomChild/index.vue';
export default {
name:'child-dom',
components: {
childDomChild
},
props:["foo"],
inheritAttrs:false,
}
</script>
<style scoped>
.child{
color: rgb(32, 28, 13);
border: 4px solid slateblue;
margin: 16px;
}
</style>
- 孙组件更新:
<template>
<div class="son">
<span>孙组件:</span>
<p>zoo:{{ zoo }}</p>
<button @click="startUpRocket">我要发射火箭</button>
</div>
</template>
<script>
export default {
name: "childDomChild",
props: ["zoo"],
inheritAttrs: false,
methods: {
startUpRocket() {
this.$emit("upRocket",'孙组件参数:哈哈哈');
console.log("孙组件要发射火箭-->startUpRocket");
}
}
};
</script>
<style scoped>
.son {
margin: 16px;
color: tomato;
border: 3px solid violet;
}
</style>