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

如何自定义Lexical.js的FORMAT_TEXT_COMMAND实现字体族设置

问题解答

核心结论

不支持直接扩展内置的FORMAT_TEXT_COMMAND传入字体参数实现字体切换。
这个命令的内置处理逻辑、可接收的payload值是Lexical核心写死的,默认只识别bold/italic/underline/strikethrough/code/subscript/superscript这几个内置文本格式,传入Arial这类字体名不会被识别处理,甚至可能触发类型报错。

对齐加粗/斜体逻辑的字体切换实现方案

你要实现「给选中文本包裹带font-family内联样式的标签、支持点击切换开关、和内置格式行为一致」的效果,按照Lexical的扩展规范走自定义节点+自定义命令的路径即可,实现逻辑和内置文本格式完全同源:

  1. 扩展自定义文本节点
    基于内置TextNode派生专属的字体文本节点,新增fontFamily属性,重写DOM渲染逻辑给输出的DOM节点加对应内联样式,同时补全JSON序列化、DOM导入导出方法,保证复制粘贴、内容保存解析正常。
    参考代码:
    import { TextNode, $applyNodeReplacement } from 'lexical';
    
    export class FontFamilyTextNode extends TextNode {
      static getType() {
        return 'font-family-text';
      }
    
      static clone(node) {
        return new FontFamilyTextNode(node.__text, node.__fontFamily, node.__key);
      }
    
      constructor(text, fontFamily = undefined, key) {
        super(text, key);
        this.__fontFamily = fontFamily;
      }
    
      createDOM(config) {
        const dom = super.createDOM(config);
        if (this.__fontFamily) {
          dom.style.fontFamily = this.__fontFamily;
        }
        return dom;
      }
    
      updateDOM(prevNode, dom) {
        const baseUpdated = super.updateDOM(prevNode, dom);
        if (prevNode.__fontFamily !== this.__fontFamily) {
          dom.style.fontFamily = this.__fontFamily || '';
          return true;
        }
        return baseUpdated;
      }
    
      setFontFamily(fontFamily) {
        const self = this.getWritable();
        self.__fontFamily = fontFamily;
        return this;
      }
    
      getFontFamily() {
        return this.getLatest().__fontFamily;
      }
    
      // 按需补全exportJSON、importJSON、importDOM方法即可
    }
    
    // 初始化编辑器时,把这个节点传入editor配置的nodes数组中
    export function $createFontFamilyTextNode(text, fontFamily) {
      return $applyNodeReplacement(new FontFamilyTextNode(text, fontFamily));
    }
    
  2. 定义专属字体格式命令
    不要复用内置的FORMAT_TEXT_COMMAND,单独创建字体切换命令:
    import { createCommand } from 'lexical';
    export const FORMAT_FONT_FAMILY_COMMAND = createCommand('FORMAT_FONT_FAMILY_COMMAND');
    
  3. 注册命令处理逻辑
    在编辑器初始化完成后注册命令,处理逻辑和内置加粗/斜体的逻辑完全一致:获取当前选区,遍历选中的文本节点,切换节点的fontFamily属性,已经是目标字体就移除样式实现开关效果。
    参考代码:
    import { $getSelection, $isRangeSelection, $isTextNode, COMMAND_PRIORITY_EDITOR } from 'lexical';
    
    editor.registerCommand(
      FORMAT_FONT_FAMILY_COMMAND,
      (targetFontFamily) => {
        const selection = $getSelection();
        if (!$isRangeSelection(selection)) return false;
    
        selection.getNodes().forEach(node => {
          if ($isTextNode(node)) {
            // 普通TextNode可先替换为自定义字体节点再设置属性
            let targetNode = node;
            if (!(node instanceof FontFamilyTextNode)) {
              targetNode = $createFontFamilyTextNode(node.getTextContent(), undefined);
              node.replace(targetNode);
            }
            if (targetNode.getFontFamily() === targetFontFamily) {
              targetNode.setFontFamily(undefined);
            } else {
              targetNode.setFontFamily(targetFontFamily);
            }
          }
        });
        return true;
      },
      COMMAND_PRIORITY_EDITOR
    );
    
  4. 工具栏按钮派发自定义命令
    把你原来按钮里派发的命令换成自定义的字体命令即可:
    <button
      onClick={() => {
        editor.dispatchCommand(FORMAT_FONT_FAMILY_COMMAND, 'Arial');
      }}
    >
      Arial
    </button>
    

如果你不想从零写整套逻辑,可以直接用官方生态里@lexical/rich-text提供的内置字体格式能力,已经封装好了节点、命令和工具栏逻辑,行为和加粗、斜体等内置格式完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:54:17