vue3 + ts + markdown-it +hljs 实现网页端DeepSeek页面,流式输出、中止回答、markdown格式转化、代码高亮,关键技术点梳理

完整代码包含很多定制代码,不贴出来了,只放关键代码

1、使用fetch实现流式输出,并拼接为一个字符串展示

try {
		const response = await fetch('https://xxxx', {//你的Api地址
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
			},
			body: JSON.stringify(你的参数),
			signal: abortController.signal, // 使用 signal 来控制请求
		});
		if (!response.ok) {
			throw new Error('Network response was not ok');
		}
		const reader = response.body?.getReader();
		const decoder = new TextDecoder('utf-8');
		let accumulatedContent = '';
		if (reader) {
			while (true) {
					const { done, value } = await reader.read();
					if (done) {
						//此处代表输出完毕可做自定义操作
						break;
					}
					const chunk = decoder.decode(value, { stream: true });
					const parsedChunk = JSON.parse(chunk);
					accumulatedContent += parsedChunk.message.content;//最终拼接成一个完整字符串
					scrollToBottom();
			}
		}
	} catch (error: any) {//用于终止流式输出时抛出异常
		if (error.name === 'AbortError') {
			console.log('Fetch aborted:', error);
		} else {
			console.error('Fetch error:', error);
		}
	}

2、终止流式输出,当流式输出没结束时,可手动触发事件暂停输出

//终止回答
const abortController = new AbortController();
const stopRequest = () => {
	abortController.abort()
};

3、窗口自动滚动到底部,在聊天记录的窗口上绑定一个ref:messagesRef

const scrollToBottom = () => {
	nextTick(() => {
		const messagesContainer = messagesRef.value;
		if (messagesContainer) {
			messagesContainer.scrollTop = messagesContainer.scrollHeight;
		}
	});
};

4、markdown格式展示和代码高亮

安装

npm install markdown-it 
npm install highlight.js 

使用

//页面展示
<div v-html="md.render(最终流式输出拼接成的字符串)"></div>
//js引入
import hljs from 'highlight.js';
import javascript from 'highlight.js/lib/languages/javascript';
import 'highlight.js/styles/ir-black.css';
import MarkdownIt from 'markdown-it';
hljs.registerLanguage('javascript', javascript);
let md: MarkdownIt = MarkdownIt({
	highlight: function (str: string, lang: string) {
		const language = hljs.getLanguage(lang);
		if (language) {
			try {
				return `<div>
                        <div>
                            <span>${lang}</span>
                        </div>
                        <div class="hljs">
                            <code>${hljs.highlight(lang, str, true).value}</code>
                        </div>
                    </div>`;
			} catch (error) {
				console.error(error);
			}
		}
		return `<div class="hl-code">
                <div>
                    <span>${lang}</span>
                </div>
                <div class="hljs">
                    <code>${md.utils.escapeHtml(str)}</code>
                </div>
            </div>`;
	},
});

5、流式输出如果一次输出多个json对象,则不能像上文一样直接转换,做如下处理

//解析json(由于流式输出可能一次输出多个json,此处需要额外处理)
const extractJsonObjects = (str: string): any[] => {
	const jsonObjects: any[] = [];
	let depth = 0;
	let start = 0;
	for (let i = 0; i < str.length; i++) {
		switch (str[i]) {
			case '{':
				if (depth === 0) start = i;
				depth++;
				break;
			case '}':
				depth--;
				if (depth === 0) {
					const jsonStr = str.substring(start, i + 1).trim();
					try {
						const parsedJson = JSON.parse(jsonStr);
						jsonObjects.push(parsedJson);
					} catch (e) {
						console.error('Invalid JSON:', jsonStr);
					}
				}
				break;
		}
	}

	return jsonObjects;
};

然后在上文fetch部分做如下修改

				const chunk = decoder.decode(value, { stream: true });
				const jsonObjects = extractJsonObjects(chunk);
				for (const jsonObject of jsonObjects) {
					if (jsonObject.message && jsonObject.message.content) {
						const messageContent = jsonObject.message.content;
						accumulatedContent += messageContent;
						messagesParams.value.messages[messagesParams.value.messages.length - 1].content = accumulatedContent;
						scrollToBottom();
					}
				}
### 实现 Markdown 流式渲染的方法和工具 #### 使用 Vue3 和 Vite 进行动态更新 为了实现在 HTML 页面上动态更新 Markdown 内容而不需页面刷新,Vue3 结合 Vite 提供了一种高效的解决方案[^3]。通过这种方式,开发者可以在前端构建响应迅速的应用程序。 - **框架选择**:Vite 作为新一代快速冷启动的构建工具,搭配 Vue3 能够显著提升开发效率。 - **Markdown 解析库**:`markdown-it` 是一个强大的 Markdown 解析器,在此场景下被选为渲染核心工具来处理转换逻辑。 ```javascript import { ref, onMounted } from &#39;vue&#39; import MarkdownIt from &#39;markdown-it&#39; const md = new MarkdownIt() export default { setup() { const contentHtml = ref(&#39;&#39;) function updateContent(markdownText) { contentHtml.value = md.render(markdownText) } onMounted(() => { // 假设这里有一个异步获取 Markdown 文本的过程 fetch(&#39;/api/get-markdown&#39;) .then(response => response.text()) .then(text => updateContent(text)) }) return { contentHtml, updateContent } } } ``` 这段代码展示了如何创建一个简单的 Vue 组件用于实时加载并展示来自 API 的 Markdown 数据,并将其转化为 HTML 显示给用户。 #### PyWebIO 应用中的流式输出 对于 Python 开发者来说,PyWebIO 提供了一个简洁的方式来实现 Web 界面下的 Markdown 流式输出功能[^4]。该库允许直接在浏览器端呈现由后端计算产生的 Markdown 格式的文本内容。 ```python from pywebio.output import put_markdown, toast from time import sleep def stream_output(): for i in range(5): text = f"# Step {i}\nThis is step number {i}." put_markdown(text).send() sleep(1) if __name__ == &#39;__main__&#39;: stream_output() ``` 上述例子说明了怎样每隔一秒推送一段新的 Markdown 格式的信息至客户端显示出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值