🚀 Vue3 + AI 流式输出实战:像“打字机”一样与大模型对话!⌨️✨
你有没有想过,当你在和 ChatGPT 或通义千问聊天时,那些文字是一个字一个字“蹦”出来的?就像有人在键盘上现场敲给你看一样——这可不是魔法,而是现代 Web 的一项酷炫技术:流式输出(Streaming Response)。
今天,我们就用 Vue3 搭建一个超有趣的 AI 对话应用,实现「边生成、边显示」的丝滑体验,让你的网页也能拥有“打字机”般的 AI 互动效果!🖨️💨
准备好了吗?Let’s go!
🎯 为什么要做流式输出?
想象一下这个场景:
你问 AI:“讲个喜羊羊与灰太狼的故事,200 字。”
普通方式:你点提交 → 等 5 秒 → “唰”一下全文弹出。
流式输出:你点提交 → 马上看到“从前,在青青草原上……”一个字一个字冒出来,仿佛 AI 正在思考并书写。
💡 用户体验差在哪?
- 普通请求像是“寄信”:发出去,等回信,期间干不了啥。
- 流式请求更像是“打电话”:对方一边说,你一边听。
所以,流式输出 = 更快感知反馈 + 更强交互沉浸感。用户不会觉得“卡住了”,而是感觉“正在发生”。
🔧 技术栈一览
我们这次要用到的技术非常精简但强大:
- ✅ Vue3 +
<script setup>—— 现代前端开发首选 - ✅
ref响应式系统 —— 数据一变,视图自动更新 - ✅ Fetch API + ReadableStream —— 实现流式读取的核心
- ✅ TextDecoder —— 解码二进制流为可读文本
- ✅ DeepSeek API —— 国产优秀大模型平台(免费可用!)
💬 提示:本文代码已完整可运行,复制即用,记得配置你的 API Key 哦!
🧱 第一步:初始化项目
npm init vite
选择:
- Framework:
Vue - Variant:
JavaScript
然后安装依赖、启动项目:
cd your-project-name
npm install
npm run dev
Vite 快如闪电⚡,几秒内就能看到欢迎页面!
🧩 三明治结构:.vue 文件的秘密
Vue 单文件组件(SFC)就像一份三明治🥪:
<script setup> <!-- 馅料1:逻辑 -->
// JS 代码写这里
</script>
<template> <!-- 馅料2:模板 -->
<div>我是页面</div>
</template>
<style scoped> <!-- 馅料3:样式 -->
div { color: red; }
</style>
今天我们只聚焦核心功能:让 AI 的回答像打字机一样“打”出来。
🔁 响应式数据:ref() 是灵魂
Vue 的精髓在于——你不用手动操作 DOM。
比如我们要展示一个问题和它的回答:
import { ref } from 'vue'
const question = ref('讲个喜羊羊的故事')
const content = ref('')
这里的 ref() 创建的是“响应式对象”。当 .value 改变时,模板会自动刷新!
举个🌰:
setTimeout(() => {
content.value = '我是一只快乐的小羊~'
}, 2000)
两秒后,页面上的 {{ content }} 就会自动更新!是不是很神奇?🧠
🤖 调用 AI 大模型:开启智能之旅
我们使用 DeepSeek API,它支持 stream: true 模式,非常适合做流式输出。
先设置请求参数:
const endpoint = 'https://api.deepseek.com/chat/completions'
const headers = {
"Authorization": `Bearer ${import.meta.env.VITE_DEEPSEEK_API_KEY}`,
"Content-Type": "application/json"
}
⚠️ 别忘了在
.env文件中添加你的密钥:VITE_DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
🌊 核心突破:如何处理“流式响应”?
这才是本文最精彩的部分!🔥
普通的 await response.json() 是等全部结果回来才解析。但我们想要“边来边显示”。
这时候就要用到 HTML5 的 ReadableStream:
const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
let done = false
while (!done) {
const { value, done: doneReading } = await reader.read()
done = doneReading
const chunk = buffer + decoder.decode(value)
buffer = ''
// 处理 SSE 格式:data: {...}
const lines = chunk.split('\n').filter(line => line.startsWith('data: '))
for (const line of lines) {
const raw = line.slice(6) // 去掉"data: "
if (raw === '[DONE]') {
done = true
break
}
try {
const data = JSON.parse(raw)
const text = data.choices[0]?.delta?.content
if (text) {
content.value += text // 逐段追加!
}
} catch (err) {
buffer = line // 解析失败就暂存
}
}
}
🎯 关键点解析:
| 技术 | 作用 |
|---|---|
response.body.getReader() | 获取流读取器 |
TextDecoder | 将 Uint8Array 转为字符串 |
data: {...} | Server-Sent Events (SSE) 协议格式 |
buffer 缓冲区 | 防止数据被截断导致 JSON 解析失败 |
👉 这样就能做到:AI 每生成一个 token,页面就多显示一个字,宛如现场写作!
💬 实际效果演示
假设你输入:
“讲一个喜羊羊与灰太狼的故事,200字”
你会看到这样的输出过程:
从前,在青青草原上……
住着一群可爱的小羊。
喜羊羊聪明勇敢,总是能识破灰太狼的诡计……
一天,灰太狼又想出了新花样……
他伪装成送快递的……
却被沸羊羊一眼识破!
大家哈哈大笑,灰太狼又一次失败而归。
虽然他总说“我一定会回来的”,但其实……
他已经悄悄喜欢上了红太狼做的蛋炒饭。
故事告诉我们:善良和智慧才是真正的力量!
每个字都像是“打”出来的,体验感拉满!🎥
🛠️ 模板部分也很重要
我们的界面很简单,但足够说明问题:
<template>
<div class="container">
<div>
<label>请输入:</label>
<input class="input" v-model="question"/>
<button @click="askLLM">提交</button>
</div>
<div class="output">
<label>启用流式输出</label>
<input type="checkbox" v-model="stream">
<div>{{ content }}</div>
</div>
</div>
</template>
用了 v-model 实现双向绑定,用户输入实时同步到 question,点击按钮触发 askLLM()。
还可以通过勾选 checkbox 控制是否开启流式模式,方便对比体验差异!
🎨 简单美化一下
加点 CSS 让它不那么“程序员风”:
.container {
padding: 20px;
font-family: 'Arial', sans-serif;
max-width: 800px;
margin: 0 auto;
}
.input {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 8px 16px;
background: #2d8cf0;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.output {
margin-top: 20px;
min-height: 300px;
white-space: pre-wrap;
background: #f9f9f9;
padding: 15px;
border-radius: 6px;
border: 1px dashed #ddd;
}
现在看起来是不是专业多了?😎
🚨 注意事项 & 常见坑
-
API Key 安全性
不要把 Key 写死在代码里!使用import.meta.env.VITE_XXX,且不要提交.env到 Git。 -
流式数据可能断片
网络传输中 JSON 可能被切开,必须用buffer缓存未完成的部分。 -
错误处理要到位
加try/catch,避免因一条坏数据导致整个流崩溃。 -
关闭流?不需要
浏览器会自动处理reader.close(),我们只需关注done信号。
🌈 扩展思路:还能怎么玩?
- ✅ 添加“停止生成”按钮,中断流读取
- ✅ 支持 Markdown 渲染(用
marked库) - ✅ 历史记录保存(localStorage)
- ✅ 语音朗读(Web Speech API)
- ✅ 多轮对话(维护
messages数组)
未来你可以把它做成自己的 AI 助手面板🤖,甚至接入微信公众号后台!
📝 总结:前端也能玩转 AI!
通过本文,你学会了:
✅ 如何用 Vue3 构建响应式界面
✅ 如何调用 LLM API 并处理 JSON 响应
✅ 如何使用 ReadableStream 实现流式输出
✅ 如何优雅地处理 SSE 数据格式
✅ 如何提升 AI 交互的用户体验
🎉 一句话总结:
“让用户早点看到第一个字,比让他等五秒看到全部更重要。”
这就是流式输出的魅力所在。
📣 最后彩蛋:试试这些有趣的问题!
- “用鲁迅的口吻批评拖延症”
- “如果孙悟空去考公务员,面试题会是什么?”
- “写一首关于前端工程师的诗,藏头‘BUG难改’”
- “让马冬梅和贾宝玉一起破案”
看看 AI 是如何一字一句“表演”出来的吧!🎭
)
💬 评论区互动:你还想让 AI 怎么“表演”?留言告诉我,下期我们一起实现!
🔖 标签推荐:#Vue3 #AI #流式输出 #前端开发 #DeepSeek #大模型 #WebStream #掘金热门 #CSDN精选