LLM独立对话框的实现

444 阅读2分钟

前言

青训营结束后有一个关于LLM对话框的小demo要求,于是便制作了一个界面雏形。

image.png 话不多说来看看如何实现的吧!!

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>