$scopedSlots
因为父页面使用了 header slot 所以会有打印
因为父页面没有使用了 footer slot 所以会有打印undefined
image.png
parent 页面
<template>
<div>
<h1>父页面</h1>
<TestSlot>
<template #header="{ data }">
父页面定义的头部{{ data }}
</template>
<template #default="{ first }">
{{ first }}
</template>
</TestSlot>
</div>
</template>
<script>
import TestSlot from './components/TestSlot'
export default {
components: {
TestSlot
}
}
</script>
child 页面
<template>
<div style="border: 1px solid red;">
<h1>子页面</h1>
<div>
<slot name="header" :data="user">我是头部</slot>
</div>
<div>
<slot name="footer">我是底部</slot>
</div>
<slot :first="user"></slot>
</div>
</template>
<script>
export default {
data(){
return {
user:{
name: 'userName',
age: 18
}
}
},
mounted() {
// 父页面 使用的 插槽 可以打印出
console.log(this.$scopedSlots.header) // Fun
console.log(this.$scopedSlots.content) // undefined
}
}
</script>
$attrs, $props, $listeners
image.png
$attrs:将父页面的 v-bind绑定数据穿透传递至下级页面,如果你在某一个组件中注册了props 那么后续的组件就无法通过$attrs 来获取你已经注册过props的属性
$props:当此页面有注册的props 你可以在 template 中 使用 $props 来获取你注册的props属性
$listeners:使$emit 可以跨越更多的层级,也可以在中间的组件中进行监听,让每一个组件都可以监听到事件
注意
$attrs是可以在 template与 script 中使用的
$props 只可以在 template 中 使用
$attrs与$props可以使用在三级组件通信, 如果更多 还是推荐使用 provide / inject 来传递
下面是以上三种API的demo
page 页面
<template>
<div class="page">
page
<Parent
:age="18"
@clickGreatGrandson="clickGreatGrandson"
/>
</div>
</template>
<script>
import Parent from './components/Parent'
export default {
components: { Parent },
methods: {
clickGreatGrandson(e) {
console.log('page', e)
}
}
}
</script>
<style scoped>
.page {
margin: 50px auto;
border: 1px solid red;
width: 800px;
height: 700px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>
Parent 页面
<template>
<div class="parent">
Parent Components
<span style="color: red;">$props: {{ $props }}</span>
<span style="color: red;">$attrs: {{ $attrs }}</span>
<Son
v-bind="$attrs"
v-on="$listeners"
@clickGreatGrandson="clickGreatGrandson"
/>
</div>
</template>
<script>
import Son from './Son'
export default {
inheritAttrs: true,
// props: [ 'age' ],
components: { Son },
mounted() {
console.log('Parent', this.$attrs)
},
methods: {
clickGreatGrandson(e) {
console.log('Parent', e)
}
}
}
</script>
<style scoped>
.parent {
border: 1px solid red;
margin: 10px;
width: 600px;
height: 500px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>
Son 页面
<template>
<div class="son">
Son Components
<span style="color: red;">$props: {{ $props }}</span>
<span style="color: red;">$attrs: {{ $attrs }}</span>
<GreatGrandson
v-bind="$attrs"
v-on="$listeners"
@clickGreatGrandson="clickGreatGrandson"
/>
</div>
</template>
<script>
import GreatGrandson from './GreatGrandson'
export default {
components: { GreatGrandson },
mounted() {
console.log('Son', this.$attrs)
},
methods: {
clickGreatGrandson(e) {
console.log('Son', e)
}
}
}
</script>
<style scoped>
.son {
border: 1px solid red;
width: 500px;
height: 300px;
margin: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>
GreatGrandson 页面
<template>
<div class="great-grandson">
GreatGrandson Components
<span style="color: red;">$props: {{ $props }}</span>
<span style="color: red;">$attrs: {{ $attrs }}</span>
<el-button type="primary" @click="clickGreatGrandson">GreatGrandson</el-button>
</div>
</template>
<script>
export default {
mounted() {
console.log('GreatGrandson', this.$attrs)
},
methods: {
clickGreatGrandson() {
this.$emit('clickGreatGrandson', 'hello i\'m clickGreatGrandson')
}
}
}
</script>
<style scoped>
.great-grandson {
border: 1px solid red;
width: 400px;
height: 200px;
margin: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>