不知道大家有没有买 Switch 呢?
虽然兔兔没有 Switch,
但我知道有游戏片都不便宜呀!
然後,游戏总会有玩腻的时候
这时候就要把记忆卡插槽里的卡片拿出来,
接着插一张新的
进去。
不过其实,
你不知道有没有发现,
我们自定义的元件都是只有标签,
都没在里面放内容呢?
<Box :number="1" />
<Box :number="2">
</Box>
我们目前都是把所有的资料丢在属性,
可是其实原生的写法应该要可以做到这样:
<Box>1</Box>
<Box>2</Box>
但你会发现在自定义的元件之中这样用是没反应的
。
WHY?
我们接下来就来谈谈为什麽!
如果要像前面所说,想要可以跟原生的写法一样能够在里面加上内容的话,Slot
就是你要找的功能!
不过我们就要解释一下为何得靠其他功能来解决,而不能直接放在里面。
让我们先看看元件实际上的意义:
<!-- 看起来的样子 -->
<Menu />
<!-- 实际上的样子 -->
<ul>
<li>首页</li>
<li>关於</li>
<li>卖场</li>
<li>服务</li>
</ul>
没错,就是做结构简化
和整理
。
那麽如果今天在元件内加入内容呢?
<!-- 看起来的样子 -->
<Menu>
这是我们的选单。
</Menu>
<!-- 实际上的样子 -->
<ul>
<li>首页</li>
<li>关於</li>
<li>卖场</li>
<li>服务</li>
</ul>
没反应,因为他不知道你要把这些内容实际上是要安排在 template 中的哪里!
没错,就是这麽简单的问题。
所以 slot 的功能就是要用来告诉 vue 我们要把内容插在
实际上结构的哪个地方
。
而其实 slot 的用法很单纯又简单,
我们只要加上 <slot></slot>
就好。
举例:
<!-- Menu.vue -->
<template>
<ul>
<slot></slot>
<li v-for="link in links">{{ link }}</li>
</ul>
</template>
<script>
export default {
data() {
return {
links: ["首页","关於","卖场","服务"]
}
}
}
</script>
那麽效果就会是这样:
<!-- 看起来的样子 -->
<Menu>
这是我们的选单。
</Menu>
<!-- 实际上的样子 -->
<ul>
这是我们的选单。
<li>首页</li>
<li>关於</li>
<li>卖场</li>
<li>服务</li>
</ul>
是不是很轻松简单?
但你可能会纳闷:
「目前这个效果用 props 也能做到啊!」
噢,没错,你说的对。
不过这样呢?
<!-- 看起来的样子 -->
<Menu>
<div>
<img src="banner.jpg" />
<span>欢迎光临 myfone</span>
</div>
</Menu>
<!-- 实际上的样子 -->
<ul>
<div>
<img src="banner.jpg" />
<span>欢迎光临 myfone</span>
</div>
<li>首页</li>
<li>关於</li>
<li>卖场</li>
<li>服务</li>
</ul>
如果今天要抛入的是元素
,是不是就很困难啦?
但是使用 slot 就简单太多啦!
其实应该也没有很明确的使用时机,
不过多半会用在需要替换内容
的元件,比如 modal。
而有时候使用他是为了架构清晰
,保持与视觉一致
。
还有一点我觉得很重要的,
就是如果你要 跨祖孙元件交换资料
的时候,
可以更方便。
因为这麽做等於平坦化,
原本要祖孙元件沟通,现在可以降维成父子元件沟通。
举例:
<!-- 主画面 -->
<div>
<List @modify="change($event)" />
</div>
<!-- List.vue -->
<div>
<div>标题</div>
<ul>
<Item v-for="i in 10" @modify="$emit('modify', $event)" />
</ul>
</div>
<!-- Item.vue -->
<li>
<input type="text" />
<button @click="$emit('modify', text)">修改</button>
</li>
像上述这样的祖孙结构,
资料传递起来就很麻烦。
因为你 props 跟 emit 可能都需要连传两层。
但为何说 slot 可以平坦化、降成父子关系?
看了就明白了:
<!-- 主画面 -->
<div>
<List>
<Item v-for="i in 10" @modify="$emit('modify', $event)" />
</List>
</div>
<!-- List.vue -->
<div>
<div>标题</div>
<ul>
<slot>
目前没有任何文章。
</slot>
</ul>
</div>
<!-- Item.vue -->
<li>
<input type="text" />
<button @click="$emit('modify', text)">修改</button>
</li>
顺带一提,slot 是可以给予预设内容的,在没有从外部填入内容之前,可以维持显示预设内容。
这样我在主画面之中就可以直接对 Item 元件存取了,
而且结构上看起来可读性比较高。
不过这种用法还是要经过考虑和评估,
因为如果太滥用,等於所有资料都得跑在父层上,
太混杂了,肯定维护起来不容易。
(就跟以不好的观念使用 vuex 一样,很可怕。)
其实不只可以有一个插槽,也可以有 N 个。
只是,结构里面就一个区域啊,
怎麽知道我要指定插到哪个插槽?
这时候就是具名插槽
该登场的时候啦~
具名插槽也很简单,就是这样定义:
<!-- Menu.vue -->
<template>
<ul>
<slot name="title"></slot>
<li v-for="link in links">{{ link }}</li>
</ul>
<slot name="description"></slot>
</template>
<script>
export default {
data() {
return {
links: ["首页","关於","卖场","服务"]
}
}
}
</script>
对,简单的加上 name,然後使用时只要像 v-on:
、v-bind:
那类的语法一般,加上 v-slot:
以及名称。
不过必须用 <template></template>
将区块包裹起来。
所以就会是这样:
<!-- 使用时看起来的样子 -->
<Menu>
<template v-slot:title>
这是我们的选单。
</template>
<template v-slot:description>
选单项目将会不定时更新,敬请期待。
</template>
</Menu>
<!-- 实际上的样子 -->
<ul>
这是我们的选单。
<li>首页</li>
<li>关於</li>
<li>卖场</li>
<li>服务</li>
</ul>
选单项目将会不定时更新,敬请期待。
什麽? 你期待这个也有短语法
?
我说你啊,人不能这麽懒,
而且这种功能要什麽短...
等等,还真的有!
试着用 #
来替代 v-slot
当缩短语法:
<Menu>
<template #title>
这是我们的选单。
</template>
<template #description>
选单项目将会不定时更新,敬请期待。
</template>
</Menu>
嘿,丢啦!
这样就可以了。
「兔兔! 元件放到插槽之後,就没办法吃到前一层元件的变数了欸,那这样怎麽办!」
哈哈哈哈哈!
当然不会有这麽不方便的事情存在啊!
其实插槽是有 Props
的!
我们来看看该如何帮插槽设置 props:
<!-- Menu.vue -->
<template>
<div>
{{ title }}
</div>
<div>
<ul>
<slot :list="links"></slot>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
title: "选单",
links: ["首页","关於","卖场","服务"]
}
}
}
</script>
就跟一般平时你给 props 的方式一模一样!
不过存取的方式不一样:
<Menu v-slot="slotProps">
<li v-for="item in slotProps.list">
{{ item }}
</li>
</Menu>
要透过在 v-slot
後加上 ="slotProps"
。
slotProps 是 slot 预设的 props 组名称,传递过来的 props 都是 slotProps 下的一个属性。
当然我们也能解构:
<Menu v-slot="{ list }">
<li v-for="item in list">
{{ item }}
</li>
</Menu>
这样能存取到上层的变数,是不是又更方便了呢!
(虽然我想不太到使用时机)
哇! slot 就这麽介绍了!
其实还有一些更细部的功能啦,
但那些应该要自己去阅读文件,
我的 vue 篇主要是为了,
把我们之後做元件会用到的功能都先带过一遍。
那其实 vue 篇就这样结束啦!
(帮 vue 篇完结洒花)
我们後面接着就要来开始实作元件了!
好期待,不知道大家会不会觉得好玩呢?
关於兔兔们:
( # 兔兔小声说 )
在你们的国度,驾照都是用鸡腿换的。
在兔兔这里,你们知道用的是什麽吗?
「红萝卜!」
啧啧啧,你以为红萝卜在我这里这麽好价嘛!
那可是相当於米饭的存在欸!来,凑近点,我告诉你答案。
其实是:黄根!!
<<: DAY 13 『 Realm 新增、修改、删除 』Part1
昨天说到了将资料订阅出来渲染在页面上的事,那麽就就来说说 RxJs 解订阅这件事吧。 这也是为了避免...
图片来源:https://www.epochtimes.com/b5/18/1/5/n100268...
在疫情的情况之下,所有的节奏都被打乱了,在全球都在这样的情况之下,大家都在求新求变,不论是办公还是教...
本日小作品: https://codepen.io/linchinhsuan/pen/OJXVgdo...
不知道大家对於 Bubble sort 的程序有没有甚麽问题呢? 今天,我们就来讨论一下程序码! 我...