☰
Vue极简ChatGPT前端实现:连续对话与Markdown渲染
2026/10/26 15:56:12 网站建设 项目流程

1. 项目概述:打造一个极简但功能完整的ChatGPT前端应用

最近一直在研究如何将ChatGPT的API能力整合到自己的前端项目中,经过多次迭代终于实现了一个功能完整但代码极简的解决方案。这个Vue项目不仅支持连续对话、Markdown渲染,还能将对话记录保存在本地存储中。对于想要快速集成AI对话功能的开发者来说,这个方案特别实用。

这个项目最核心的价值在于:用最少的代码实现了最实用的功能组合。很多现成的ChatGPT客户端要么功能过于复杂,要么缺少关键的连续对话能力。而我们的实现方案只需要不到300行代码就能搞定所有核心功能,特别适合作为二次开发的基础模板。

2. 技术选型与架构设计

2.1 为什么选择Vue作为前端框架

Vue.js的响应式特性和组件化开发模式特别适合这类实时交互应用。相比React,Vue的模板语法更直观,学习曲线更平缓;而对比原生JavaScript,Vue的数据绑定能大幅减少DOM操作代码。在这个项目中,我们主要利用了以下Vue特性:

  • 组合式API(Composition API):用setup函数组织代码逻辑,比Options API更灵活
  • 响应式系统:自动追踪数据变化并更新UI
  • 单文件组件:将HTML、CSS和JavaScript封装在一个.vue文件中

2.2 核心功能模块划分

整个应用可以划分为四个主要模块:

  1. 对话管理模块:处理消息的发送、接收和存储
  2. Markdown渲染模块:将AI返回的Markdown内容转换为HTML
  3. 本地存储模块:使用localStorage保存对话历史
  4. UI交互模块:处理用户输入和界面反馈

这种模块化设计使得每个功能都可以独立开发和测试,也便于后续扩展。

3. 实现连续对话功能

3.1 对话上下文管理

ChatGPT的API本身是无状态的,要实现连续对话,我们需要在客户端维护对话历史。具体实现方式是:

const conversation = ref([ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Hello!' }, { role: 'assistant', content: 'Hi there! How can I help you today?' } ]);

每次发送新消息时,我们都将整个对话历史发送给API,这样AI就能根据上下文生成回复。

3.2 优化对话体验的技巧

在实际使用中发现几个提升体验的关键点:

  1. 限制历史记录长度:过长的对话会消耗更多token,可以设置一个合理的上限(如最近10条消息)
  2. 添加加载状态:在等待AI回复时显示加载动画,提升用户体验
  3. 错误处理:网络请求可能会失败,需要妥善处理错误情况
const sendMessage = async () => { loading.value = true; try { const response = await axios.post('/api/chat', { messages: conversation.value }); conversation.value.push({ role: 'assistant', content: response.data.choices[0].message.content }); } catch (error) { console.error('API请求失败:', error); } finally { loading.value = false; } };

4. Markdown渲染的实现方案

4.1 选择合适的Markdown解析器

经过对比测试,最终选择了marked.js作为Markdown解析器,原因如下:

  1. 轻量级(仅24KB)
  2. 解析速度快
  3. 支持GFM(GitHub Flavored Markdown)
  4. 可自定义渲染规则

安装和使用非常简单:

npm install marked
import { marked } from 'marked'; const renderMarkdown = (text) => { return marked.parse(text); };

4.2 安全考虑:防止XSS攻击

直接渲染用户提供的Markdown内容可能存在XSS风险。marked.js提供了sanitizer选项,但更推荐使用DOMPurify进行二次净化:

import DOMPurify from 'dompurify'; const renderMarkdown = (text) => { return DOMPurify.sanitize(marked.parse(text)); };

4.3 样式优化技巧

为了让渲染的Markdown内容更美观,可以引入GitHub风格的CSS:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css" > <div class="markdown-body" v-html="renderMarkdown(content)"></div>

5. 本地记忆功能的实现

5.1 使用localStorage保存对话历史

localStorage是浏览器提供的持久化存储方案,非常适合保存小型数据。实现原理很简单:

// 保存对话 const saveConversation = () => { localStorage.setItem('chatHistory', JSON.stringify(conversation.value)); }; // 读取对话 const loadConversation = () => { const saved = localStorage.getItem('chatHistory'); if (saved) { conversation.value = JSON.parse(saved); } };

5.2 优化存储策略

在实践中发现几个需要注意的点:

  1. 定期清理:localStorage有大小限制(通常5MB),长时间积累可能占满空间
  2. 数据压缩:可以对消息内容进行压缩后再存储
  3. 加密敏感信息:如果对话包含敏感内容,建议加密后再存储

5.3 实现多会话管理

进阶功能可以支持多个独立的对话会话:

const sessions = ref([]); const createNewSession = () => { const sessionId = Date.now().toString(); sessions.value.push({ id: sessionId, title: '新对话', createdAt: new Date() }); localStorage.setItem('sessions', JSON.stringify(sessions.value)); return sessionId; };

6. 完整代码结构与关键实现

6.1 项目目录结构

src/ ├── assets/ ├── components/ │ ├── ChatMessage.vue │ └── MarkdownRenderer.vue ├── composables/ │ ├── useChat.js │ └── useStorage.js ├── App.vue └── main.js

6.2 核心组件实现

ChatMessage.vue组件负责显示单条消息:

<template> <div :class="['message', role]"> <div class="avatar">{{ role === 'user' ? '👤' : '🤖' }}</div> <div class="content"> <MarkdownRenderer v-if="role === 'assistant'" :content="content" /> <template v-else>{{ content }}</template> </div> </div> </template>

6.3 主应用逻辑

App.vue中整合所有功能:

<script setup> import { ref, onMounted } from 'vue'; import ChatMessage from './components/ChatMessage.vue'; import { useChat } from './composables/useChat'; import { useStorage } from './composables/useStorage'; const { conversation, sendMessage, loading } = useChat(); const { loadConversation, saveConversation } = useStorage(); onMounted(() => { loadConversation(); }); </script>

7. 常见问题与解决方案

7.1 API调用限制处理

ChatGPT API有速率限制,处理方案:

  1. 添加请求队列
  2. 实现自动重试机制
  3. 在前端显示友好的错误提示
const callApiWithRetry = async (payload, retries = 3) => { for (let i = 0; i < retries; i++) { try { return await axios.post('/api/chat', payload); } catch (error) { if (i === retries - 1) throw error; await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); } } };

7.2 长消息处理技巧

当AI返回很长的消息时:

  1. 分段渲染提升性能
  2. 添加"继续阅读"按钮
  3. 实现自动滚动到最新消息
const renderLongMessage = (text) => { const chunks = []; const chunkSize = 1000; for (let i = 0; i < text.length; i += chunkSize) { chunks.push(text.slice(i, i + chunkSize)); } return chunks; };

7.3 移动端适配要点

针对移动设备的优化:

  1. 输入框固定在底部
  2. 虚拟列表优化长对话性能
  3. 手势支持(如滑动删除消息)
@media (max-width: 768px) { .chat-container { padding-bottom: 80px; } .input-area { position: fixed; bottom: 0; left: 0; right: 0; } }

8. 项目部署与扩展建议

8.1 部署选项比较

部署方式优点缺点
Vercel简单快速,适合静态站点需要处理API代理
Netlify自带CI/CD,功能丰富免费版有构建时间限制
自有服务器完全控制需要维护成本

8.2 可能的扩展方向

  1. 用户认证:支持多用户登录
  2. 主题切换:实现深色/浅色模式
  3. 插件系统:支持自定义功能扩展
  4. 语音输入:集成语音识别API
  5. 数据同步:跨设备同步对话记录

8.3 性能优化建议

  1. 使用虚拟滚动处理长对话列表
  2. 对Markdown解析结果进行缓存
  3. 按需加载大型依赖库
  4. 使用Web Worker处理耗时的计算任务
// 使用动态导入按需加载marked const renderMarkdown = async (text) => { const { marked } = await import('marked'); return marked.parse(text); };

经过实际项目验证,这套方案在保持代码简洁的同时,提供了足够强大的功能。特别是在需要快速原型开发的场景下,这种极简但完整的实现方式特别有价值。我在多个内部项目中都使用了这个模板,根据具体需求进行定制化调整,大大提高了开发效率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询