Quill Usage in Vue2-based project

75 阅读1分钟

Background

A product requirement is for a function that lets the PM add customizable text on the H5 page, which gets rendered in the app.

Step1: Choose a rich text editor package

I found these popular rich text editor package below, and compared them.

packagestarsizelicensetipshome
Quill36.8k2.29 MBBSD-3-Clause licensequilljs.com/
Slate.js27.8k1.94 MBMIT licenseBased on Reactwww.slatejs.org/examples/ri…
Draft.js22.5k1.4 MBMIT, Unknown licenses found Based on Reactdraftjs.org/
StackEdit20.6k2.71 MBApache-2.0Online Markdown editorstackedit.io/
GrapesJS18.5k5.93 MBBSD-3-Clause license grapesjs.com/

  截屏2023-08-31 17.24.16.png Quill has had rapid development over the past year. It provides all the required functions, is framework-agnostic so it can be used anywhere, and our project is Vue-based. This makes Quill the best choice for us.

Quill usage

npm install quill@1.3.6

Our database stores text as String values like

"<p><strong>test1</strong></p>"

However, Quill uses its own Delta format, which can only be used within the Quill package. This raises two issues:

  1. How can we format the Delta into a String to store in the database?
  2. If we store the String format, how do we render it back in Quill?

Using innerHTML can address the first issue of formatting the Delta into a String.

`querySelector('.ql-editor').innerHTML`

 

Regarding the second issue, the Quill source code has a convert method that can transform a String into the Delta format. This allows using quill.clipboard.convert to render the stored String back into Quill. However, this method is not documented in the Quill API reference.

截屏2023-08-31 15.45.58.png

截屏2023-08-31 15.59.59.png

Quill Component for Vue2

Based on the research described above, we can create a reusable component as follows.

<template>
  <div>
    <div ref="quillEditor"></div>
  </div>
</template>

<script>
import Quill from "quill";
import "quill/dist/quill.snow.css";
export default {
  name: "quill",
  props: {
    value: String,
  },
  data() {
    return {
      quill: null,
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      const options = {
        theme: "snow",
        modules: {
          toolbar: [
            ["bold", "italic", "underline", "strike"],
            [{ align: [] }],
            ["link"],
          ],
        },
        placeholder: "Insert text here ...",
      };
      const dom = this.$refs.quillEditor;
      this.quill = new Quill(dom, options);
      const contents = this.string2Delta(this.value);
      this.quill.setContents(contents);

      this.quill.on("text-change", () => {
        const childNode = dom.querySelector(".ql-editor").innerHTML;
        this.$emit("input", childNode);
      });
    },
    string2Delta(val) {
      return this.quill.clipboard.convert(
        `<div class='ql-editor' style="white-space: normal;">${val}<p><br></p></div>`
      );
    },
  },
};
</script>

Usage of this component

<Quill :value="<p><strong>test1</strong></p>" @input="(val) => {}"/>

截屏2023-08-31 16.54.04.png

Reference

  1. quilljs.com/docs/downlo…
  2. npm-compare.com/quill,draft…