2019年大年三十,Vue 2.6发布,其中改动最大的就是slot(插槽),今天为大家分析一下最新版的slot。
上一篇文章中已经跟大家分享了Vue 2.6中放出大招,可以点这里回看上一篇。
今天给大家着重讲一下Vue 2.6中的Slot
回顾
Vue 2.6版本之前,slot是基于W3C提出的Web Component草案设计实现的。
草案地址:https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md
所以之前版本的slot语法与W3C标准中还是很接近的。利用<slot>元素来作为承载分发内容的出口。而在vue 2.6+的版本中,将使用一个全新的指令——v-slot来替代原来的<slot>。先看一下写法的比较
默认插槽、具名插槽的对比
2.5.+和2.6.+在组件定义上的语法是相同的,定义示例如下:
<!--组件的定义-->
<div class="container">
<header>
<!--具名插槽 名称header-->
<slot name="header"></slot>
</header>
<main>
<!--默认插槽-->
<slot></slot>
</main>
<footer>
<!--具名插槽 名称footer-->
<slot name="footer"></slot>
</footer>
</div>
而在使用组件的插槽时是有区别的
2.5.+语法
<!--组件的使用-->
<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>
<template slot="footer">
<p>Here's some contact info</p>
</template>
</base-layout>
2.6.+语法
使用一个全新的指令——v-slot
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
以上是两个版本中“默认插槽”和“具名插槽”的语法对比,此时的v-slot的优势还未体现出来。下面对比一下“作用域插槽”。
作用域插槽的对比
作用域插槽组件的定义示例如下:
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
v2.5.+的slot使用
<todo-list v-bind:todos="todos">
<template slot-scope="slotProps">
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
v2.6.+的slot使用
<todo-list :todos="todos">
<template v-slot:default="{todo}">
<span v-if="todo.isComplete">✓</span>
{{todo.text }}
</template>
</todo-list>
可以看出,即使是作用域插槽中,v-slot的指令同样可以搞定。接下来仔细说说这个全新的v-slot指令
全新的v-slot指令
新老对比
<foo v-slot="{ msg }">{{ msg }}</foo>
可以看下面的例子,有更加直观的对比
老语法
<foo>
<bar slot-scope="foo">
<baz slot-scope="bar">
<div slot-scope="baz">
{{ foo }} {{ bar }} {{ baz }}
</div>
</baz>
</bar>
</foo>
新语法:
<foo v-slot="foo">
<bar v-slot="bar">
<baz v-slot="baz">
{{ foo }} {{ bar }} {{ baz }}
</baz>
</bar>
</foo>
更多变化
动态插槽名称
由于V2.6.+开始,vue支持动态参数,所以在v-slot中同样可以将插槽名动态化。
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
具名插槽的缩写
跟 v-on
和 v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容 (v-slot:
) 替换为字符 #
。例如 v-slot:header
可以被重写为 #header
:
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
总结
Vue 2.6提出了全新的v-slot指令来解决之前在插槽使用中的痛点。但是他是完全向下兼容的,所以各位不用担心升级了Vue 2.6以后之前的代码废掉,毕竟仍然在2.X版中。