在学习Vue的时候,面试的时候经常会被问到插槽,之前不会的时候让我自己封装一个tab插件的思路是什么,我傻傻的说传一个数据对象进去。。面试官就不理我了。。。
插槽主要分成三种:单个插槽,具名插槽和作用域插槽
单个插槽
单个插槽是最简单易懂的和最常用的;在模版中使用插槽可接受模版使用的时候传过来的内容,替代模版內的默认内容,向组件中传递不带 slot 特性的子元素时,比如test
中的乖乖
,这些子元素被存储在组件实例中的 $slots.default
中
有一个组件test;test模版里面的代码
<template>
<h1>hello!</h1>
<slot>使用的时候没有传入数据是我的内容显示,传入内容我就不显示</slot> //插槽的默认内容
</template>
有一个组件需要使用这个test组件,在使用的时候的用法:
<test>乖乖</test> //最后结果显示hello!乖乖
由于我实在太懒了 下面直接拿官方的例子
使用场景:
在同一样的结构下,某一个部分下需要使用不同的模版,假如我有一个页面,拥有同一样的头和尾 这个时候我就只需要给中间的部分传一个不同的slot,可以拥有不同的数据结构。我自己理解的与子组件的不同之处是这个可以传入不同的html结构,而子组件只能传入数据,结构是一样的。 还有ui组件的tab组件的内容就是使用了slot
具名插槽
有些时候我们需要多个插槽。简单来说,就是需要给插槽命名,分别窜地给名字相同的地方。对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽。定义的组件里面的代码:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot> //这个是未命名插槽,在使用的时候未指定名字的将会匹配到这里
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
在向具名插槽提供内容的时候,我们可以在一个父组件的 <template> 元素上使用 slot 特性,或者直接用在普通元素上也是可以的
<base-layout>
<template slot="header">
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p slot="footer">Here's some contact info</p>
</base-layout>
应用场景:这个比较灵活,比如一个页面有多处需要分发不同的内容的时候使用。
作用域插槽
提供的组件带有一个可从子组件获取数据的可复用的插槽。简单说来跟前面两种不同的情况就是 前面两种渲染的数据是从使用的组件决定,作用域插槽就是数据由封装的组件决定
在通过slot元素,使用v-bind的形式绑定属性传递给父元素,父元素通过slot-scope属性来接收属性
定义组件:
<ul>
<li v-for="todo in todos" :key="todo.id">
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot :todo="todo"> //这里的todo就是传递给父元素接受的数据
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
使用的时候的组件:
<todo-list v-bind:todos="todos"> 这里todo-list里面使用的数据是通过props传递进去的,也可以在子元素里面定义数据
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps"> //slotProps是接收todo-list传过来的数据的
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 定制每个待办项。-->
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
使用场景:同样的内容和数据在不同的地方使用不同的样式可使用作用域插槽。在父组件里面自定义样式。(自己的理解,可能不对)。
网友评论