Implementation of Vue quill editor customization function (undo, redo)

Posted by cowboysdude on Mon, 07 Mar 2022 04:29:49 +0100

Record the problems encountered in recent work. The requirement is to customize the undo and restore functions in Vue quil editor rich text: undo and redo.

install

npm install vue-quill-editor -S

Of course, you can also use CDN. Here we talk about NPM installation

Mount in component

import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

import { quillEditor } from 'vue-quill-editor'

export default {
  components: {
    quillEditor
  }
}

options specific configuration

editorOption: {
        placeholder: "Please enter the traceability content. The traceability content will not be included in the database", 
        modules: {
          toolbar: {
            container: [
              //Customize Toolbar options
              //Toolbar settings
              ["bold", "italic", "underline", "strike"], //Bold, italic, underline, strikeout
              ["blockquote", "code-block"], //Reference, code block

              // [{'header': 1}, {header ': 2}], / / title, form of key value pair; 1. 2 indicates font size
              [{ list: "ordered" }, { list: "bullet" }], //list
              [{ align: [] }], //Alignment
              [{ script: "sub" }, { script: "super" }], // Superscript and subscript
              ["clean"], //Clear font style

              //[{indent ':' - 1 '}, {indent': '+ 1'}], / / indent
              // [{'direction':'rtl '}], / / text direction

              [{ color: [] }, { background: [] }], // Font color
              [{ size: ["small", false, "large", "huge"] }], // font size
              [{ header: [1, 2, 3, 4, 5, 6, false] }], //Level title
              [{ font: [] }], //typeface

              ["image"], //Upload pictures and videos
              ["revoke", "redo"], //Add button
            ],
            handlers: {
              //Events added to custom buttons
              revoke: () => {
                //revoke
                this.btnundo();
              },
              redo: () => {
                //recovery
                this.btnRedo();
              },
            },
          },
        },
      },

Customize the style of the button

Define a method initButton in data, and then call this method in mounted

initButton: function () {
        //Initializes the button style in the page in use
        let revoke = document.querySelector(".ql-revoke"); //Get element
        let redo = document.querySelector(".ql-redo");
        let Front = document.createElement("i"); //Create element
        let after = document.createElement("i");
        Front.className = "el-icon-refresh-left"; //New class attribute
        after.className = "el-icon-refresh-right";
        Front.style.cssText = "font-size:18px";
        after.style.cssText = "font-size:18px";
        revoke.appendChild(Front); //Append to element
        redo.appendChild(after);
},

Realize undo redo

The idea of undo redo is to define an empty array changeText to record the changes of rich text characters. Rich text binds @ change events. Every time the rich text changes, the changeText array records once, and then click undo and redo to obtain the corresponding data. Just write the defined methods in methods. Use the editorOption configuration to call the methods in methods.

// revoke
    btnundo() {
      for (let i = 0; i < this.changeText.length; i++) {
        if (this.content == this.changeText[i]) {
          this.content = this.changeText[i - 1];
        }
      }
    },
    // recovery
    btnRedo() {
      for (let i = 0; i < this.changeText.length; i++) {
        if (this.content == this.changeText[i]) {
          this.content = this.changeText[i + 1];
          return;
        }
      }
    },
    // Rich text listening event
    EditorChange() {
      if (this.changeText.length >= 50) {
        //Limit array length
        this.changeText.shift(); //Clear first data
        this.changeText.push(this.content);
      } else {
        this.changeText.push(this.content); //Additional data
      }
    },

Chinese rich text

The style is written directly into the style

<style>
/* Rich text localization */
p {
  margin: 10px;
}

.edit_container,
.quill-editor {
  height: 300px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  content: "32px";
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "text";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "Title 1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "Title 2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "Title 3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "Title 4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "Title 5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "Title 6";
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "Standard font";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "Serif font";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "Equal width font";
}
</style>

Existing problems

Undo and redo have been basically implemented here, but there are bugs in undo and redo. Because the project has enough, we don't continue to dig deeply. Let's talk about the bugs:

1.undo is a @ change event to record rich text changes, but there is no record when the array is empty. Therefore, undo until the array is empty will not be empty. This problem should be able to write a judgment to judge whether the array is empty and change the value of two-way binding.

2.redo is the same as the @ change event to record the changes of rich text, so the change event will also be triggered to record the changes of rich text after revocation, so the same value will appear in the array. I gave return here to stop the operation of the code, but there will be some problems when it is restored to the last item of the array.

If there is a big man who knows undo redo, you can talk about it in detail. I don't think so much about how to come here. Please point out the wrong places

Topics: Javascript Front-end Vue.js