slot元素作为VUE承载分发内容的出口,也是组件的一块HTML模板,这个块模板显示不显示,以及怎样显示由父组件来决定;
1.默认插槽: 又名单个插槽或者匿名插槽;这类插槽没有具体的名字,一个组件只能有一个该类插槽.
<template>
<!-- 父组件 parent.vue -->
<div class="parent">
<h1>父容器</h1>
<child>
<div class="tmpl">
<span>菜单1</span>
</div>
</child>
</div>
</template>
<template>
<!-- 子组件 child.vue -->
<div class="child">
<slot></slot>
<h1>子组件</h1>
<slot></slot>
</div>
</template>
2. 具名插槽: 匿名插槽没有name属性,所以叫匿名插槽.那么增加了name属性,就变成了具名插槽;具名插槽可以在组件中出现N次,出现在不同的位置,只需要不同的name属性区分即可.
<template>
<!-- 父组件 parent.vue -->
<div class="parent">
<h1>父容器</h1>
<child>
<div class="tmpl" slot="up">
<span>菜单up-1</span>
</div>
<div class="tmpl" slot="down">
<span>菜单down-1</span>
</div>
<div class="tmpl" slot="up">
<span>菜单up-1</span>
</div>
<div class="tmpl" slot="default">
<span>菜单->1</span>
</div>
<div class="tmpl">
<span>菜单->10</span>
</div>
</child>
</div>
</template>
<template>
<div class="child">
<!-- 具名插槽 -->
<slot name="up"></slot>
<h3>这里是子组件</h3>
<!-- 具名插槽 -->
<slot name="down"></slot>
<slot name="up"></slot>
<!-- 匿名插槽 -->
<slot></slot>
</div>
</template>
如上图所示,slot标签会根据父容器给child标签内传入内容的slot属性值,替换对应的内容.
其实,默认插槽也有name属性,为default,同样指定slot的name值为default,一样可以显示父组件中传入的没有指定slot的内容
3. 作用域插槽: 作用域插槽可以是默认插槽,也可以是具名插槽,不一样的地方是,作用域插槽可以为slot标签绑定数据,让父组件可以获取子组件的数据.
<template>
<!-- parent.vue -->
<div class="parent">
<h1>这是父组件</h1>
<child1>
<template slot="default" slot-scope="slotProps">
{{ slotProps }}
<div v-for="item in slotProps" :key="item.id">
{{item.id}} --- {{item.name}} --- {{item.age}}
</div>
</template>
</child1>
</div>
</template>
<template>
<!-- child.vue -->
<div class="child">
<h1>这是子组件</h1>
<slot :user="user" :apple="apple"></slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
id:1,
name: '小赵',
age:18
},
apple:{
id:2,
name:"red",
age:100
}
}
}
}
</script>
如上图所示,子组件child在渲染默认插槽slot时,将数据user传递给了slot标签,在渲染过程中,父组件可以通过slot-scope属性获取到user数据并渲染视图
slot 实现原理:当子组件vm实例化时,获取到父组件传入的 slot 标签的内容,存放在vm.slot.default,具名插槽为vm.slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可曾该插槽为作用域插槽。