Vue3项目需用fetch实现Grok SSE流式响应,Pinia管理消息状态并动态更新content,useScroll配合条件滚动锚定,气泡组件剥离data:前缀渲染Markdown,CSS控制流式动画与交互禁用。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

你需要在Vue3项目中接入Grok API,实现一个能实时显示AI逐字回复的对话界面,而不是等整段响应返回后再渲染。这要求前端必须正确处理流式数据、防止DOM频繁重绘、保持消息气泡的滚动锚定,并兼容Grok官方API的SSE格式。
初始化Vue3项目并安装依赖
用Vite创建最小化Vue3项目:npm create vite@latest grok-chat -- --template vue。进入目录后执行npm install。
安装必需依赖:npm install axios pinia @vueuse/core。其中@vueuse/core提供useScroll和useEventListener等实用组合函数,对滚动锚定至关重要。
【不要安装eventsource-polyfill】 Grok的SSE响应头明确要求Content-Type: text/event-stream,而现代浏览器原生EventSource已完全支持该协议,引入polyfill反而会干扰流式中断重连逻辑。
立即学习“前端免费学习笔记(深入)”;
配置Grok API密钥与基础请求封装
在src/env.d.ts中补充类型声明:declare global { interface ImportMetaEnv { readonly VITE_GROK_API_KEY: string } }。
创建src/api/grok.ts,导出fetchStream函数:使用fetch而非axios,因为axios不原生支持SSE流式读取;设置headers为{Authorization: Bearer ${import.meta.env.VITE_GROK_API_KEY}};关键参数是{method: 'POST', body: JSON.stringify({model: 'grok-beta', messages: [{role: 'user', content: prompt}], stream: true})}。
响应体必须设为res.body.getReader(),不能用res.json()——后者会等待完整响应,彻底破坏流式特性。
构建流式消息状态管理(Pinia Store)
运行npm install pinia,然后在src/stores/chat.ts中定义useChatStore:
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
state包含messages: Message[](每个Message有id、role、content、isStreaming布尔值)、inputValue:string、isLoading:boolean;actions中addUserMessage直接push,addAIMessage则需初始化空字符串并标记isStreaming=true;最关键的是streamChunk(chunk: string)方法——它只更新最后一条AI消息的content += chunk,不触发新消息插入。
注意:messages数组必须用ref包裹,否则computed依赖无法追踪内部字符串变化;【isStreaming字段不可省略】 它是控制TypingIndicator显示/隐藏的唯一依据,缺失会导致用户误判AI是否仍在思考。
实现消息容器滚动锚定
第一步:给消息列表容器绑定ref="messageContainer",并在onMounted中调用useScroll(messageContainer)获取滚动状态。
第二步:监听store.messages变化,当新增消息或streamChunk触发时,检查当前滚动位置是否接近底部(如scrollTop + clientHeight >= scrollHeight - 50px)。
第三步:仅当满足底部条件时,执行messageContainer.value.scrollTop = messageContainer.value.scrollHeight;否则不干预——这是防止用户手动向上翻阅历史时被强制拽回底部的核心逻辑。
这一步操作起来很简单,直接把滚动判断逻辑写进watch回调里就行,但漏掉“仅当靠近底部才滚动”的条件就会导致阅读体验崩溃。
编写流式消息气泡组件
方法一:用v-for遍历messages,对每条消息动态绑定:class="{ 'ai-bubble': msg.role === 'assistant', 'user-bubble': msg.role === 'user' }"。
方法二:AI消息气泡内嵌套一个,其中renderMarkdown函数需过滤掉Grok流式返回中的data:前缀和换行符,仅保留纯文本内容——Grok的SSE分片格式为data: {"id":"...","choices":[{"delta":{"content":"hello"}}]},必须剥离JSON外壳才能安全渲染。
方法三:为AI气泡添加CSS动画效果,在.is-streaming状态下启用opacity过渡,避免文字突兀闪现;同时禁用pointer-events,防止用户在流式输出中途点击未完成的消息。

















