【quill.js】如何使用Container创建表格结构

栏目: Html · 发布时间: 4年前

内容简介:这篇文章更适合对quill.js已经有一定了解的读者,如果您是正打算调研/学习quill.js,可以通过官方文档或我之前的一篇文章《深入理解quilljs》对为了更清晰的介绍

前言

这篇文章更适合对quill.js已经有一定了解的读者,如果您是正打算调研/学习quill.js,可以通过官方文档或我之前的一篇文章《深入理解quilljs》对 Quill编辑器 有一定了解后,再来阅读这篇文章。

为了更清晰的介绍 Container 的用法,我选择使用个人基于 quill.js 实现的表格模块  quill-better-table   作为示例来讲解,因为quill.js官方内置的模块都相对简单,难以覆盖各个方面。

quill-better-table 项目地址: github.com/soccerloway…

Container类

Parchemnt是quill.js用于描述/管理编辑器内容结构及对应DOM树的底层依赖 ,  quill.js 中内置的Blot类均继承自 Parchment 的基础类,这些基础内继承自 Parchemnt 的抽象类。关于Container类的继承关系如下:

【quill.js】如何使用Container创建表格结构

其中, ShadowBlot 是所有 blot (Inline、Block、Embed、Container等)的父类。实际上,在Quill/blots的源码中, Container类 (quill.js)仅仅是继承了 Parchment 中的Container类,没有任何逻辑代码。故我们真正需要了解的是 Parchment 中的 Container类

如何定义嵌套结构及原理

接下来,我们来看看表格模块中 单元格行 (TableCellLine)、 单元格 (tableCell)的定义(为避免代码过多,影响阅读体验,format及表格业务逻辑相关的代码会省略掉,完整代码可到 这里 查看):

// TableCellLine
class TableCellLine extends Block {  ...... // create/formats/optimize等}
TableCellLine.blotName = "table-cell-line"
TableCellLine.ClassName = "qlbt-cell-line"
TableCellLine.tagName = "DIV"

// TableCell
class TableCell extends Container {
  ......
  
  checkMerge() {
    if (super.checkMerge() && this.next.children.head != null) {
      const thisHead = this.children.head.formats()["table-cell-line"]
      const thisTail = this.children.tail.formats()["table-cell-line"]
      const nextHead = this.next.children.head.formats()["table-cell-line"]
      const nextTail = this.next.children.tail.formats()["table-cell-line"]

      return (
        thisHead.cell === thisTail.cell && 
        thisHead.cell === nextHead.cell &&
        thisHead.cell === nextTail.cell
      )
    }
    return false
  }

  ......
}
TableCell.blotName = "table"
TableCell.tagName = "TD"

TableCell.allowedChildren = [TableCellLine]
TableCellLine.requiredContainer = TableCell复制代码

经过上面的定义,最终生成的HTML结构如下:

<td>
  <div class="qlbt-cell-line"></div>
  <div class="qlbt-cell-line"></div>
</td>复制代码

实际上,控制嵌套结构关系的重点就是:

checkMerge
requiredContainer

Blot.requiredContainer

定义该Blot需要被哪一个容器Blot包裹。当该Blot被创建完成后,会执行到 ShadowBlot类 中的 optimize 方法,其主要逻辑就是:检查该Blot的 requiredContainer 是否被设置,并且该Blot的父Blot不是 requiredContainer 设置的Blot类的实例,调用 wrap 方法(wrap的作用就是创建容器Blot实例,插入的该Blot的父级中,然后将该Blot插入到容器中)。

以最终生成前面的HTML结构为例,经过 wrap 的过程后,HTML结构的变化:

【quill.js】如何使用Container创建表格结构

checkMerge

该方法就是用于检查是否需要将 这个容器Blot实例它的下一个兄弟Blot实例合并为同一个容器Blot实例 。返回值为 true 则合并。 checkMerge 在Container类的 optimize 方法中调用,紧接 shadowBlot.optimize 过程。当 checkMerge 返回值为 true 时, 下一个兄弟Blot实例children 会被插入到 这个容器实例 中,得到最终HTML结构。

<td>
  <div class="qlbt-cell-line"></div>
  <div class="qlbt-cell-line"></div>
</td>复制代码

利用checkMerge阻止并列(兄弟关系)的Blot合并

通过上面的定义,我们已经能够得到 一个 支持多行的表格单元格结构了。但在实际的表格中,同一表格行中有若干个单元格,结构如下:

<tr>
  <td>
    <div class="qlbt-cell-line">1</div>
  </td>
  <td>
    <div class="qlbt-cell-line">2</div>
  </td>
  <td>
    <div class="qlbt-cell-line">3</div>
  </td>
</tr>复制代码

如何让checkMerge合适的时候返回false,阻止单元格被合并呢?让我们来看看 quill-better-table 中, TableCell类checkMerge

checkMerge() {
    if (super.checkMerge() && this.next.children.head != null) {
      const thisHead = this.children.head.formats()["table-cell-line"]
      const thisTail = this.children.tail.formats()["table-cell-line"]
      const nextHead = this.next.children.head.formats()["table-cell-line"]
      const nextTail = this.next.children.tail.formats()["table-cell-line"]

      return (
        thisHead.cell === thisTail.cell && 
        thisHead.cell === nextHead.cell &&
        thisHead.cell === nextTail.cell
      )
    }
    return false
  }复制代码

示例代码中, checkMerge 方法主要是通过检查当前 tableCell 实例和下一个 tableCell 实例的 children 的formats中属性cell是否相等,相等则合并两个单元格的内容,否则不合并。

实际上, quill-better-table 在定义 TableCellLine 的时候,为它定义了表示单元格和行的唯一标识符,设置到domNode的属性上了,且通过formats方法能够得到这些信息,TableCellLine的DOM结构为:

<div class="qlbt-cell-line" data-row="row-xaes" data-cell="cell-hsop">复制代码

checkMerge 方法既是通过这个唯一符,也是 data-cell 的值来区别 td 是否需要被合并。依照这样的方式,我们就能够一层一层的把表格结构相关的Blot全部定义出来。最终实现在Quill编辑器中插入表格。

注意:像表格这种多层嵌套的内容结构,需要在最内层把唯一标识符都设计好,quill.js中嵌套结构的基础在最内层,然后一层一层wrap和merge,在wrap的时候把所需要的唯一标识符往外传递和使用。

结语

表格相关Blot的定义,以及表格编辑常用功能的实现涉及到的具体细节太多,在这里不赘述,有兴趣的同学可以到我的 quill-better-table 开源项目的源代码中查看具体实现细节,相信对将要在Quill中使用Container的同学大有帮助。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Golden Ticket

The Golden Ticket

Lance Fortnow / Princeton University Press / 2013-3-31 / USD 26.95

The P-NP problem is the most important open problem in computer science, if not all of mathematics. The Golden Ticket provides a nontechnical introduction to P-NP, its rich history, and its algorithmi......一起来看看 《The Golden Ticket》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具