You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单个TextField中实现不同字号与样式的文本效果

实现支持富文本样式的TextField组件

要让输入的不同字符呈现差异化的字号、颜色、样式,不能依赖原生的input或textarea——它们只能统一设置样式。核心方案是用contenteditable元素模拟输入框,维护一个富文本片段数组,给每个片段单独配置样式。

核心思路

  • 用数组存储富文本片段,每个片段包含文本内容和对应的样式属性(如fontSize、color、fontWeight等)
  • 用contenteditable的div作为输入容器,将每个片段渲染为带内联样式的span
  • 通过Selection API跟踪光标位置,处理输入、删除时的片段更新,以及样式切换逻辑

具体实现(以React为例)

1. 初始化富文本状态

import { useState } from 'react';

const RichTextField = () => {
  // 初始化示例片段:对应需求中的示例
  const [richSegments, setRichSegments] = useState([
    { text: 'AA', style: { fontWeight: 'bold' } },
    { text: 'BBaS', style: { fontStyle: 'italic' } },
    { text: ' OKEY MAN', style: {} },
    { text: '!', style: { fontWeight: 'bold' } }
  ]);

2. 渲染富文本内容

把每个片段转换成带样式的span,注入到contenteditable容器中:

const renderRichContent = () => {
    return richSegments.map((seg, idx) => {
      // 将样式对象转为内联样式字符串
      const styleStr = Object.entries(seg.style)
        .map(([key, val]) => `${key}: ${val}`)
        .join('; ');
      return `<span style="${styleStr}">${seg.text}</span>`;
    }).join('');
  };

3. 渲染输入容器与样式控制按钮

return (
    <div className="rich-text-wrapper">
      <div className="style-controls">
        <button onClick={() => toggleStyle('fontWeight', 'bold')}>粗体</button>
        <button onClick={() => toggleStyle('fontStyle', 'italic')}>斜体</button>
        <input
          type="color"
          onChange={(e) => setCurrentColor(e.target.value)}
          placeholder="选择颜色"
        />
      </div>
      <div
        contentEditable
        className="rich-text-input"
        onInput={handleInput}
        dangerouslySetInnerHTML={{ __html: renderRichContent() }}
      />
    </div>
  );
};

4. 处理输入与样式切换逻辑

// 处理输入内容更新
  const handleInput = (e) => {
    const selection = window.getSelection();
    if (!selection.rangeCount) return;
    const range = selection.getRangeAt(0);
    const targetSpan = range.commonAncestorContainer.closest('span');
    if (!targetSpan) return;

    const segIndex = Array.from(e.currentTarget.children).indexOf(targetSpan);
    const updatedSegments = [...richSegments];
    updatedSegments[segIndex].text = targetSpan.textContent;
    setRichSegments(updatedSegments);
  };

  // 切换指定样式(如粗体、斜体)
  const toggleStyle = (styleKey, targetValue) => {
    const selection = window.getSelection();
    if (!selection.rangeCount) return;
    const range = selection.getRangeAt(0);
    const targetSpan = range.commonAncestorContainer.closest('span');
    if (!targetSpan) return;

    const segIndex = Array.from(document.querySelector('.rich-text-input').children).indexOf(targetSpan);
    const updatedSegments = [...richSegments];
    const currentVal = updatedSegments[segIndex].style[styleKey];
    updatedSegments[segIndex].style = {
      ...updatedSegments[segIndex].style,
      [styleKey]: currentVal === targetValue ? 'normal' : targetValue
    };
    setRichSegments(updatedSegments);
  };

  // 设置文本颜色
  const setCurrentColor = (color) => {
    const selection = window.getSelection();
    if (!selection.rangeCount) return;
    const targetSpan = selection.getRangeAt(0).commonAncestorContainer.closest('span');
    if (!targetSpan) return;

    const segIndex = Array.from(document.querySelector('.rich-text-input').children).indexOf(targetSpan);
    const updatedSegments = [...richSegments];
    updatedSegments[segIndex].style = {
      ...updatedSegments[segIndex].style,
      color
    };
    setRichSegments(updatedSegments);
  };

5. 基础样式(CSS)

.rich-text-wrapper {
  width: 400px;
  margin: 20px;
}

.style-controls {
  margin-bottom: 8px;
  gap: 8px;
  display: flex;
}

.rich-text-input {
  border: 1px solid #ddd;
  padding: 10px;
  min-height: 120px;
  border-radius: 4px;
  outline: none;
  font-size: 16px;
}

.rich-text-input:focus {
  border-color: #2196f3;
}

示例效果对应中文表述

=> TextFieldForm - [ AA BBaS OKEY MAN**!** ]

内容的提问来源于stack exchange,提问作者Skyonave Light

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 10:45:38