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

Quill调用setContents()时自定义属性被删除的问题排查

Quill自定义块属性被移除的原因及解决方法

问题原因

你当前的实现存在两个核心问题:

  • 混淆了块级Blot与文本属性的使用方式:你创建的TestBlot是继承自Block的独立块级元素(对应<testblot>标签),但在Delta中却将testblot作为文本的attributes来设置。Quill的Delta规则中,块级Blot属于嵌入内容,需要以insert: { 自定义blot名: 配置 }的形式存在,而非文本属性。
  • 自定义Blot缺少必要的序列化/反序列化逻辑:你的TestBlot仅定义了blotName和tagName,没有实现create、serialize等核心方法,导致Quill无法正确识别并持久化这个Blot的状态。

解决方法

根据你的需求(给特定块添加识别属性),分两种场景给出解决方案:

场景1:给现有块元素(如<p>)添加自定义属性

如果你不需要新的标签,只是想给默认块添加自定义标识属性,可扩展原生Block并覆盖其格式处理逻辑:

// testblot.blot.ts
import Quill from 'quill';

const Block = Quill.import('blots/block');

export class TestBlot extends Block {
  // 保持原生blotName,覆盖原有Block实现
  static blotName = 'block';
  static tagName = 'P';

  // 从DOM节点读取自定义属性
  static formats(node: HTMLElement) {
    const formats = super.formats(node);
    if (node.hasAttribute('data-testblot')) {
      formats.testblot = node.getAttribute('data-testblot') === 'true';
    }
    return formats;
  }

  // 应用自定义属性到DOM节点
  format(name: string, value: any) {
    if (name === 'testblot') {
      if (value) {
        this.domNode.setAttribute('data-testblot', 'true');
      } else {
        this.domNode.removeAttribute('data-testblot');
      }
    } else {
      super.format(name, value);
    }
  }
}

注册后,即可在Delta中正常使用该属性:

const ops = [
  {
    attributes: { testblot: true },
    insert: title,
  },
];
quillEditorInstance.setContents(ops);
// 此时getContents()能正确获取到testblot属性

场景2:创建独立的自定义块级元素(如<testblot>)

如果你确实需要新的块标签,需完善自定义Blot的核心方法,并调整Delta的写法:

// testblot.blot.ts
import Quill from 'quill';

const Block = Quill.import('blots/block');

export class TestBlot extends Block {
  static blotName = 'testblot';
  static tagName = 'TESTBLOT';

  // 创建DOM节点
  static create(value: any) {
    const node = super.create(value);
    // 可根据传入value设置属性
    if (value) {
      node.setAttribute('data-testblot', 'true');
    }
    return node;
  }

  // 序列化Blot为Delta数据
  static value(node: HTMLElement) {
    return node.hasAttribute('data-testblot') ? true : false;
  }
}

注册后,Delta需按嵌入内容的方式编写:

const ops = [
  // 插入自定义块
  { insert: { testblot: true } },
  // 在块内插入文本
  { insert: title },
  // 插入换行结束当前块
  { insert: '\n' },
];
quillEditorInstance.setContents(ops);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:38:01