前言
青训营结束后有一个关于LLM对话框的小demo要求,于是便制作了一个界面雏形。
话不多说来看看如何实现的吧!!
vue插槽
插槽也是vue组件通信的一种方式。我们已经了解到组件能够接收任意类型的 JavaScript 值作为 props,但组件要如何接收模板内容呢?在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。于是我们可以运用插槽这一方式。与之前的组件通信不同插槽是直接传递代码片段,其它的方式更多的是传递值。我定义了一个layout组件作为子组件。下边是layout的具体代码!!
<template>
<div class="container">
<aside class="aside">
<slot name="aside">
</slot>
</aside>
<header class="header">
<slot name="header">
</slot>
</header>
<main class="main">
<slot name="main">
</slot>
</main>
<footer class="footer">
<slot name="footer">
</slot>
</footer>
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.aside{
height: 100vh;
width: 30vw;
background-color:hsl(5, 10%, 15%);
}
.container {
display: flex;
align-items: flex-start; /* 或者其他对齐方式 */
}
.header{
width: 70vw;
height: 10vh;
}
.footer{
width: 70vw;
position: fixed;
bottom: 20px;
margin-left: 30vw;
}
</style>
从代码可看出我的layout组件,有四个部分aside侧边栏、header、main、footer四个部分并且每个部分的slot都命名了独特的名字-(具名插槽), 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在那里被渲染。
要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 <template> 元素,并将目标插槽的名字传给该指令:v-slot 有对应的简写 #,
因此 template v-slot:header> 可以简写为 <template #header>。其意思就是“将这部分模板片段传入子组件的 header 插槽中”。我这个layout组件可以进行复用,当其他页面也需要这样布局的时候可以拿来复用(代码片段传入不同而已)。
接下来看看父组件吧!!
<template>
<div>
<Layout>
<template v-slot:aside >
<Aside></Aside>
</template>
<template v-slot:header>
<Header></Header>
</template>
<template v-slot:main>
<Main></Main>
</template>
<template v-slot:footer>
<Footer></Footer>
</template>
</Layout>
</div>
</template>
<script setup>
import Layout from "@/components/layout.vue";
import Aside from "@/components/aside.vue";
import Header from "@/components/header.vue";
import Main from "@/components/main.vue";
import Footer from "@/components/footer.vue";
</script>
<style lang="scss" scoped>
</style>
如上代码,我自己定义了四个组件:Aside、Header、Main、Footer。分别组为代码片段传递给子组件layout。 以下是这四个组件的代码
<template>
<div style="text-align: right;">
<i class="iconfont icon-shousuojiantouQ"></i>
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
i{
font-size: 40px;
color: whitesmoke;
}
</style>//aside
<template> //header
<div class="parent">
<div class="son1">
<div>
<i class="iconfont icon-liaotiankuang" style="font-size: 18px"></i>
<h1 style="display: inline-block;font-size: 20px">Introducting Claude,AI Assistant</h1>
<i class="iconfont icon-xiajiantou" style="font-size: 18px"></i>
</div>
</div>
<div class="son2">
<i class="iconfont icon-star" style="font-size: 25px"></i>
<i class="iconfont icon-luntaituoyin" style="font-size: 25px"></i>
<i class="iconfont icon-xiaoxi" style="font-size: 25px"></i>
</div>
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.parent {
display: flex;
justify-content: flex-end;
align-items: center; /* 垂直居中 */
}
.son1{
width: 90%;
display: flex;
justify-content: center;
}
.son2 {
display: flex;
width: 10%;
justify-content: space-between;
}
</style>
<template> //footer
<div class="box">
<div class="son">
<i class="iconfont icon-yishangchuanwenjian">
</i>
<i class="iconfont icon-zhaoxiangji"></i>
</div>
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.box {
border: 1px solid darkgray;
border-radius: 5px;
width: 50%;
margin-left: 20%;
height: 20vh;
display: flex;
}
.son {
width: 10%;
margin-left: auto;
display: flex;
justify-content: space-evenly;
}
</style>