用vue3写一个AI聊天室

效果图如下:

1、页面布局:

<template>
  <div class="body" style="background-color: rgb(244, 245, 248); height: 730px">
      <div class="container">
        <div class="right">
          <div class="top">AI问答</div>
          <div class="chat" ref="chatContainer">
            <div
              v-for="(item, i) in msgList"
              :key="i"
              :class="item.type == '1' ? 'rightMsg' : 'leftMsg'"
            >
              <img
                v-if="item.type == '0'"
                src="../assets/images/AI.png"
                alt=""
              />
              <div class="msg">{
  { item.content }}</div>
              <img
                v-if="item.type == '1'"
                src="../assets/images/me.png"
                alt=""
              />
            </div>
            <!-- 
            <div v-if="msgList.length >= 10" class="separator">
              -------------- 本AI问答仅显示最近10条对话 --------------
            </div> -->
          </div>
          <div class="bottom">
            <input v-model="value" placeholder="请输入您想提问的内容" />
            <button @click="onSend">
              <img src="../assets/images/send.png" alt="发送" />
            </button>
          </div>
        </div>
      </div>
  </div>
</template>

2、封转函数(用户输入问题和AI回答问题):

const msgList = reactive([]);
//提问
const userQuestion = 
### Vue2 实现 AI 聊天对话框 #### 创建基本结构 为了构建一个简单的AI聊天对话框,在HTML文件中定义了一个容器来容纳所有的消息。每一条消息及其对应头像被放置在一个`div`内,并且此`div`应用了特定样式类以便于布局控制[^1]。 ```html <div id="app"> <div class="message-container" v-scroll> <div v-for="(msg, index) in messages" :key="index" :class="[msg.isMe ? &#39;right_layout_myselfChat&#39; : &#39;left_layout_otherChat&#39;]"> <img :src="msg.avatarUrl" alt="User Avatar" class="user_img"/> <p>{{ msg.text }}</p> </div> </div> <!-- 输入区域 --> <input type="text" v-model="newMessage" @keyup.enter="sendMessage" placeholder="Type a message..." /> </div> ``` #### 添加CSS样式 对于上述提到的消息项,通过`.user_img`类名设置了头像的尺寸和其他属性;而对于整个消息列表,则利用了自定义滚动行为确保新消息能够立即进入视野范围[^2]。 ```css .message-container { max-height: 400px; overflow-y: auto; } .right_layout_myselfChat, .left_layout_otherChat { display: flex; align-items: center; margin-bottom: 8px; } .user_img { width: 40px; height: 40px; border-radius: 50%; } ``` #### 定义Vue实例与逻辑处理 接下来初始化Vue实例并配置数据绑定以及事件监听器。这里还实现了发送消息的功能——每当用户按下回车键时触发相应函数向数组追加新的对象表示的新消息记录。此外,也包含了模拟接收来自服务器响应的过程[^3]。 ```javascript // 自定义指令用于自动滚动到最新消息位置 Vue.directive(&#39;scroll&#39;, { inserted(el) { el.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" }); } }); new Vue({ el: &#39;#app&#39;, data() { return { newMessage: &#39;&#39;, messages: [ // 初始化一些测试数据... ] }; }, methods: { sendMessage() { if (!this.newMessage.trim()) return; const myMsg = this.createMessage(this.newMessage, true); this.messages.push(myMsg); this.newMessage = &#39;&#39;; // 模拟异步获取回复 setTimeout(() => { const botReply = `You said "${myMsg.text}"`; this.messages.push(this.createMessage(botReply)); }, 1000); }, createMessage(text, isMe=false) { return { text, avatarUrl: isMe ? &#39;/path/to/my-avatar.png&#39; : &#39;/path/to/bot-avatar.png&#39;, isMe }; } } }); ``` #### 实现逐字显示效果 为了让用户体验更加生动有趣,可以在接收到机器人的回应之后采用逐步显现的方式呈现文字内容而不是一次性全部加载出来。这可以通过JavaScript中的定时器机制轻松完成,类似于jQuery的做法但在Vue环境中可以直接操作组件内部的状态变量而不需要依赖DOM查询选择器[^4]。 ```javascript methods: { ..., simulateTypingEffect(messageIndex) { let currentText = &#39;&#39;; const fullText = this.messages[messageIndex].text; function updateDisplay() { currentText += fullText[currentText.length]; Vue.set( app.messages[messageIndex], &#39;text&#39;, currentText ); if (currentText !== fullText) { setTimeout(updateDisplay, Math.random() * (70 - 30) + 30); } } updateDisplay(); } }, watch: { messages(newVal) { newVal.forEach((_, idx) => { if (_ === newVal.length - 1 && !_.isMe) { nextTick().then(() => this.simulateTypingEffect(idx)); } }); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值