AI?了,发现了一个有点意思的东西,就是逐字展示,以下就是它的实现方式
vue3+ts实现
一、setTimeout
<template> <div> <button @click="startDisplayStr">逐字展示</button><br /> <p>{{ displayedText }}</p> </div></template><script setup lang="ts">import { ref } from 'vue'const streamList = ref(['首先需要避免暴饮暴食,尽量保持规律的饮食习惯,避免过度饥饿或过饱。', '其次,应避免摄入过多油腻食物和高脂肪食物,以免加重胰腺负担。', '此外,还应注意控制饮酒量,避免酒精对胰腺的损害。'])const currIndex = ref(0)const displayedText = ref('') // 正在显示的文字let timer: number | null = nullconst startDisplayStr = () => { if (timer) { clearTimeout(timer!) } // 将数组中的字符串拼接起来 const res = streamList.value.join('') if (currIndex.value < res.length) { displayedText.value += res[currIndex.value] currIndex.value++ setTimeout(startDisplayStr, 200) } else { clearTimeout(timer!) timer = null }}</script><style scoped></style>
二、setInterval
<template> <div> <button @click="getStream">逐字展示</button><br /> <p>{{ displayedText }}</p> </div></template><script setup lang="ts">import { ref } from 'vue'const streamList = ref(['首先需要避免暴饮暴食,尽量保持规律的饮食习惯,避免过度饥饿或过饱。', '其次,应避免摄入过多油腻食物和高脂肪食物,以免加重胰腺负担。', '此外,还应注意控制饮酒量,避免酒精对胰腺的损害。'])const currIndex = ref(0)const displayedText = ref('') // 正在显示的文字let timer: number | null = nullconst getStream = () => { timer = setInterval(displayAnswer, 200) })}const displayAnswer = () => { const text = streamList.value.join('') displayedText.value += text[currIndex.value] currIndex.value++ if (currIndex.value == text.length) { clearInterval(timer!) timer = null }}</script><style scoped></style>
react+js
setInterval
import { useState, useRef, useEffect } from 'react';import { Button } from 'antd';const Xiaoan = () => { const [stream, setStream] = useState('') const [answerOutput, setAnswerOutput] = useState('') // 正在显示的文字 const typingRef = useRef(null); // 使用ref来存储定时器ID const [isShowing, setIsShowing] = useState(false); // 是否开始展示 const start = () => { setStream('这是一条测试语句') setIsShowing(true) } // 逐字展示答案 const timeoutTextHandle = (callback) => { let currIndex = 0 const chars = stream.split('') const timer = setInterval(() => { if (currIndex < chars.length) { setAnswerOutput(prev => prev + chars[currIndex]) callback(chars[currIndex]) // 每增加一个字符调用回调,将当前的字符传给回调函数 currIndex++ } else { clearInterval(timer) setIsShowing(false) } }, 200) typingRef.current = timer } useEffect(() => { // 监听变量,触发函数 if (isShowing && stream) { let fullChar = '' history.current.push({type: 'ai', message: ''}) timeoutTextHandle(char => { fullChar += char let index = history.current.length - 1 history.current[index]['message'] = fullChar }) } return () => { // 组件卸载时,清除定时器 if (typingRef.current) { clearInterval(typingRef.current); } }; }, [isShowing, stream]) return ( <div> <Button onClick={start}>开始</Button> <div>展示:{answerOutput}</div> </div> )}export default Xiaoan