插槽
可以理解为子组件在自己身上挖了一个坑 —— 占位符,当父组件引用子组件并想在子组件内填充内容时,就可以使用插槽。插槽也分匿名插槽、具名插槽以及作用域插槽,话不多说,直接上代码!
一、匿名插槽
<!-- 子组件 -->
<template>
<div class="son">
<header>我是头部</header>
<!-- slot标签 - 在子组件内挖一个坑 -->
<slot>匿名插槽 - 默认内容</slot>
<footer>我是底部</footer>
</div>
</template>
<!-- 父组件 -->
<template>
<div class="father">
<Son></Son>
</div>
</template>
运行结果:
当父组件需要填充内容时:
<!-- 父组件 -->
<template>
<div class="father">
<Son>
<div>父组件填充的内容</div>
</Son>
</div>
</template>
运行结果:
注意:父组件填充的内容会覆盖子组件内slot标签里定义的默认内容,如果定义了多个匿名插槽,则会拷贝多份父组件填充的内容!
<!-- 子组件 -->
<template>
<div class="son">
<header>我是头部</header>
<!-- slot标签 - 这回挖三个坑 -->
<slot>匿名插槽 - 默认内容</slot>
<slot>匿名插槽 - 默认内容</slot>
<slot>匿名插槽 - 默认内容</slot>
<footer>我是底部</footer>
</div>
</template>
<!-- 父组件 -->
<template>
<div class="father">
<Son>
<div>父组件填充的内容</div>
</Son>
</div>
</template>
运行结果:
虽然我们可以定义多个匿名插槽,但在开发中推荐一个组件中只使用一个,最好使用具名插槽。
二、具名插槽
注意:
<div slot="插槽名"></div>
上述这种在父组件插入内容,使用具名插槽的方式在Vue2.6+的版本中已被废弃但未被移除。(就是还能用,但不推荐用),在Vue2.6+版本中推荐使用新语法:v-slot指令。
<!-- 子组件 -->
<template>
<div class="son">
<header>我是头部</header>
<!-- slot标签 - 具名插槽坑, 通过name属性定义插槽名 -->
<slot name="one">具名插槽one - 默认内容</slot>
<slot name="two">具名插槽two - 默认内容</slot>
<footer>我是底部</footer>
</div>
</template>
<!-- 父组件 -->
<template>
<div class="father">
<Son></Son>
</div>
</template>
父组件不插入任何内容,运行结果:
注意:v-slot指令只能用在template标签中,并且可以用#号代替v-slot。
<!-- 父组件 -->
<template>
<div class="father">
<Son>
<template #one>
<div>填充内容one</div>
<div>填充内容one1</div>
<div>填充内容one11</div>
</template>
<template #two>
<div>填充内容two</div>
<div>填充内容two2</div>
<div>填充内容two22</div>
</template>
</Son>
</div>
</template>
子组件没任何改变,运行结果:
注意:在父组件插入内容时,v-slot冒号后不要有空格,会识别不了要使用的插槽,直接显示默认内容。
三、作用域插槽
1.什么是作用域插槽(初学时我也很懵)
作用域插槽就是带有数据的插槽,就是让父组件在填充子组件内容时也能使用子组件的数据。
注意:在Vue2.6+版本后,具名插槽与作用域插槽的使用都推荐使用v-slot指令,旧版本中具名插槽的slot属性与作用域插槽的slot-scope属性都已废弃但未移除。
2.使用方法(上代码!)
<!-- 子组件 -->
<template>
<div class="son">
<header>我是头部</header>
<!-- slot标签 - 通过v-bind将当前子组件的say数据暴露给父组件 -->
<slot v-bind:say="say">作用域插槽 - 默认内容</slot>
<footer>我是底部</footer>
</div>
</template>
<script>
export default {
data() {
return {
say: '我是子组件请来的救兵~',
};
},
};
</script>
<!-- 父组件 -->
<template>
<div class="father">
<Son>
<!-- 匿名插槽也是有"名字"的 - default -->
<!-- 此时, 可以从子组件拿到一个存有数据的对象 -->
<!-- user 用来保存子组件的数据 -->
<template #default="user">
<div>子组件的数据: {{ user }}</div>
</template>
</Son>
</div>
</template>
运行结果:
注意:匿名插槽也是有“名字”的,default就是匿名插槽的名字,在作用域插槽中要使用具名插槽的话,选个名字就好了~
<!-- 子组件 -->
<template>
<div class="son">
<header>我是头部</header>
<!-- slot标签 - 通过v-bind将当前子组件的say数据暴露给父组件 -->
<slot name="one" v-bind:say1="say1">作用域插槽one - 默认内容</slot>
<slot name="two" v-bind:say2="say2">作用域插槽two - 默认内容</slot>
<footer>我是底部</footer>
</div>
</template>
<script>
export default {
data() {
return {
say1: '我是one请来的救兵~',
say2: '我是two请来的救兵~',
};
},
};
</script>
<!-- 父组件 -->
<template>
<div class="father">
<Son>
<!-- 匿名插槽也是有"名字"的 - default -->
<!-- 此时, 可以从子组件拿到一个存有数据的对象 -->
<!-- user 用来保存子组件的数据 -->
<template #one="user1">
<div>子组件的数据: {{ user1 }}</div>
</template>
<template #two="user2">
<div>子组件的数据: {{ user2 }}</div>
</template>
</Son>
</div>
</template>
运行结果:
至此,插槽的基础知识整理完毕,作用域中拿到的是对象,怎么调用到数据就不用我多说了吧~