开发预览 更新于 2026-05-10

StreamingText 流式文本

SSE / token-by-token 文本逐字渲染,光标动画,可选轻量 markdown 解析。

基础用法

接收累计 text 字符串和 done 标志:父组件每次拼接新 token 后传入完整字符串,组件负责渲染并显示闪烁光标。完成后 done={true} 隐藏光标。format="markdown" 启用轻量解析(段落、codebolditalic、换行),不引入 markdown-it / remark。

背景 视口

src/App.vue
<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref } from 'vue';
import { CfStreamingText, CfButton } from '@chufix-design/vue';

const full = 'ChuFix UI is a **Vue + React** component library with OKLCH tokens, _three themes_, and `cf-*` class prefixes. This demo streams the message one token every 40ms.';
const text = ref('');
const done = ref(false);
let timer: ReturnType<typeof setInterval> | null = null;

function start() {
  if (timer) clearInterval(timer);
  text.value = '';
  done.value = false;
  let i = 0;
  timer = setInterval(() => {
    i += 1;
    text.value = full.slice(0, i);
    if (i >= full.length) {
      if (timer) clearInterval(timer);
      timer = null;
      done.value = true;
    }
  }, 40);
}

onMounted(start);
onBeforeUnmount(() => { if (timer) clearInterval(timer); });
</script>
<template>
  <div class="demo-stack">
    <CfStreamingText :text="text" :done="done" format="markdown" />
    <CfButton variant="tertiary" size="sm" @click="start">重放</CfButton>
  </div>
</template>
<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue';
import { CfStreamingText, CfButton } from '@chufix-design/vue';

const full = 'ChuFix UI is a **Vue + React** component library with OKLCH tokens, _three themes_, and `cf-*` class prefixes. This demo streams the message one token every 40ms.';
const text = ref('');
const done = ref(false);
let timer= null;

function start() {
  if (timer) clearInterval(timer);
  text.value = '';
  done.value = false;
  let i = 0;
  timer = setInterval(() => {
    i += 1;
    text.value = full.slice(0, i);
    if (i >= full.length) {
      if (timer) clearInterval(timer);
      timer = null;
      done.value = true;
    }
  }, 40);
}

onMounted(start);
onBeforeUnmount(() => { if (timer) clearInterval(timer); });
</script>
<template>
  <div class="demo-stack">
    <CfStreamingText :text="text" :done="done" format="markdown" />
    <CfButton variant="tertiary" size="sm" @click="start">重放</CfButton>
  </div>
</template>
import { useEffect, useState } from 'react';
import { CfButton, CfStreamingText } from '@chufix-design/react';

export default function Demo() {
  const full = 'ChuFix UI is a **Vue + React** component library with OKLCH tokens, _three themes_, and `cf-*` class prefixes. This demo streams the message one token every 40ms.';
  const [text, setText] = useState('');
  const [done, setDone] = useState(false);
  let timer: ReturnType<typeof setInterval> | null = null;

  function start() {
    if (timer) clearInterval(timer);
    setText('');
    setDone(false);
    let i = 0;
    timer = setInterval(() => {
      i += 1;
      setText(full.slice(0, i));
      if (i >= full.length) {
        if (timer) clearInterval(timer);
        timer = null;
        setDone(true);
      }
    }, 40);
  }

  onMounted(start);
  onBeforeUnmount(() => { if (timer) clearInterval(timer); });
  return (
    <>
      <div className="demo-stack">
          <CfStreamingText text={text} done={done} format="markdown" />
          <CfButton variant="tertiary" size="sm" onClick={start}>重放</CfButton>
        </div>
    </>
  );
}
import { useEffect, useState } from 'react';
import { CfButton, CfStreamingText } from '@chufix-design/react';

export default function Demo() {
  const full = 'ChuFix UI is a **Vue + React** component library with OKLCH tokens, _three themes_, and `cf-*` class prefixes. This demo streams the message one token every 40ms.';
  const [text, setText] = useState('');
  const [done, setDone] = useState(false);
  let timer= null;

  function start() {
    if (timer) clearInterval(timer);
    setText('');
    setDone(false);
    let i = 0;
    timer = setInterval(() => {
      i += 1;
      setText(full.slice(0, i));
      if (i >= full.length) {
        if (timer) clearInterval(timer);
        timer = null;
        setDone(true);
      }
    }, 40);
  }

  onMounted(start);
  onBeforeUnmount(() => { if (timer) clearInterval(timer); });
  return (
    <>
      <div className="demo-stack">
          <CfStreamingText text={text} done={done} format="markdown" />
          <CfButton variant="tertiary" size="sm" onClick={start}>重放</CfButton>
        </div>
    </>
  );
}

API

属性类型默认说明
textstring当前累计文本
donebooleanfalse完成则隐藏光标
format'text' | 'markdown''text'渲染模式
cursor'blink' | 'block' | 'none''blink'光标样式

反馈与讨论

StreamingText 流式文本 的讨论

0
0 / 600
正在加载评论...