slot和v-slot解决样式需要不断重复的问题
遇到问题
今天我在网上做vue开源项目的时候发现,如果要做多页面,样式该咋办?难道每个都一个一个插入吗?这样重复就是罪过,万一需求改变每个都改该多麻烦!
所以我看了vue官方文档,发现有一个slot功能
eg
<template>
<div class="nav-wrapper">
<div class="content">
111
</div>
<Nav/>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
name:'money'
});
</script>
<style lang="scss" scoped>
.nav-wrapper {
border: 1px black solid;
display: flex;
flex-direction: column;
height: 100vh;
}
.content {
overflow: auto;
border: 1px solid blue;
flex-grow: 1;
}
</style>
这是一个页面的vue文件,如果每个页面样式相似都要写这么多真的浪费时间而且不符合美观
所以我想到把重复的内容封装到一个component里面,我暂且命名为Layout
//Layout.vue
<template>
<div class="nav-wrapper">
<div class="content">
</div>
<Nav/>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
name:'Layout'
});
</script>
<style lang="scss" scoped>
.nav-wrapper {
border: 1px black solid;
display: flex;
flex-direction: column;
height: 100vh;
}
.content {
overflow: auto;
border: 1px solid blue;
flex-grow: 1;
}
</style>
而删除了这些重复内容,原本的vue就变得干净清爽多了
<template>
<p>
111
</p>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
name:'money'
});
</script>
接下来把Layout组件在全局引用后,我们遇到一个问题,如何把这个111的p标签引入到Layout组件中呢
通过不断翻阅Vue文档,找到一个方法,也就是这次的主角slot
slot
slot他只有一个属性就是
name - string
,是用于命名插槽。
它的用法就是
<slot> 元素作为组件模板之中的内容分发插槽。<slot> 元素自身将被替换。
//Layout.vue
<template>
<div class="nav-wrapper">
<div class="content">
<slot></slot>
</div>
<Nav/>
</div>
</template>
这样就会把外面传进来的把slot标签代替
但是这种方法是不够全面,而且Vue文档也说已经废弃但是没有移除,那咋样才能跟好呢?因为无法针对性的插入,比如遇到不同页面样式不同就没辙了
所以我们可以采用V-slot标签
v-slot
-
预期:可放置在函数参数位置的 JavaScript 表达式 (在支持的环境下可使用解构)。可选,即只需要在为插槽传入 prop 的时候使用。
-
参数:插槽名 (可选,默认值是
default
) -
限用于
<template>
- 组件 (对于一个单独的带 prop 的默认插槽)
-
用法:
提供具名插槽或需要接收 prop 的插槽。
-
示例:
<!-- 具名插槽 --> <base-layout> <template v-slot:header> Header content </template> Default slot content <template v-slot:footer> Footer content </template> </base-layout> <!-- 接收 prop 的具名插槽 --> <infinite-scroll> <template v-slot:item="slotProps"> <div class="item"> {{ slotProps.item.text }} </div> </template> </infinite-scroll> <!-- 接收 prop 的默认插槽,使用了解构 --> <mouse-position v-slot="{ x, y }"> Mouse position: {{ x }}, {{ y }} </mouse-position>
跟 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>
然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:
<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
{{ user.firstName }}
</current-user>
如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>