Quill 富文本编辑器二次封装

Quill 富文本编辑器二次封装

Quill 是一个很流行的富文本编辑器,github 上 star 大约 21k。但是很少项目中使用时直接使用它,都要对其进行二次封装,你作为一个页面仔是挡不住有想法的产品经理的。

安装 quill 库

  • 原生应用中使用
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet" />
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
  • spa 应用中使用
// npm install quill
import Quill from "quill";

实例化 Quil 对象

实例化 Quill,挂载到当前上下文中,然后就能使用它的相关方法及属性

import Quill from "quill";
import "quill/dist/quill.snow.css";

const options = {
  debug: "warn",
  modules: {
    toolbar: [
      ["bold", "italic", "underline", "blockquote"],
      [{ align: "justify" }, { align: "center" }, { align: "right" }]
      // ['link', 'image'],
    ]
  },
  placeholder: this.props.placeholder || "请输入内容...",
  readOnly: false,
  theme: "snow"
};

const quill = new Quill(".my-editer", options); // 将其实例化到dom树上.my-editor的节点上

getSelection

我们在插入内容时,要得知几个必要条件:

  • 1、从哪里开始插入
  • 2、插入的内容是什么 (文字、图片、标题、视频、音频)?
  • 3、插入的内容是否需要格式化?(标题的话,需要插入文本然后格式化成标题格式)

那么 getSelection() 方法便是用来获取光标的,就让我们知道了现在用户光标置于何处,那么就知道了第一个条件

this.quill.getSelection();

insertText

insertText() 方法是插入文本用的,一般都会在插入后,格式化其他格式,所以下面的方法基本要连用

format

format() 方法是格式化数据的,能将文本格式化成链接、标题、对齐、大小等等

// 格式化成标题
this.quill.insertText(section_index, getFieldValue("title"));
this.quill.getSelection();
this.quill.format(
  "header",
  toolbar[activeToolIndex].value,
  getFieldValue("title")
);

// 格式化成链接
getFieldValue("link") && this.quill.format("link", getFieldValue("link"));

on

on() 是监听某些变化用的,比如 text-change,就是在富文本中的编辑内容更改时会触发,这里面会处理很多的变化相关

this.quill = new Quill(".mys-editor", this.options);
this.quill.on("text-change", this.handleChange.bind(this));

注册自定义的标签

因为 quill 中的标签是有限的,如果要使用其他标签的话,需要注册进去,以 video 标签为例:

  • 同级目录下新建 quil-video.js
const Quill = require("quill");
const BlockEmbed = Quill.import("blots/block/embed");
export class VideoBlot extends BlockEmbed {
  static create(value: any) {
    let node = super.create();
    node.setAttribute("src", value.url);
    node.setAttribute("controls", value.controls);
    node.setAttribute("width", value.width);
    node.setAttribute("height", value.height);
    node.setAttribute("webkit-playsinline", true);
    node.setAttribute("playsinline", true);
    node.setAttribute("x5-playsinline", true);
    return node;
  }

  static value(node: any) {
    return {
      url: node.getAttribute("src"),
      controls: node.getAttribute("controls"),
      width: node.getAttribute("width"),
      height: node.getAttribute("height")
    };
  }
}

然后在富文本编辑器的组件中在实例化的 Quill 上注册该标签

import Quill from "quill";
import { VideoBlot } from "./quill-video";

VideoBlot.blotName = "simpleVideo";
VideoBlot.tagName = "video";
Quill.register({ "formats/simpleVideo": VideoBlot }, true);

便可以在相应的位置进行插入 video 标签了

const p = this.getSelection(); // 获取插入的光标位置
this.quill.insertEmbed(p, "simpleVideo", {
  url, // 视频的地址
  controls: "controls",
  width: "100%"
});

oss 加密引起问题

图片、视频使用三方 oss 存储,那么存在一个问题,就是回显图片时需要图片地址后面带上 ossToken,上传数据保存时,需要去除 ossToken,所以需要以下正则来实现,就是富文本最终结果是个字符串,使用正则匹配每个 img,video 标签的 src,将其对应的替换:

  • 上传时清除 ossToken
export function formatEditData(value: string) {
  const imgReg = /<img.*?(?:>|\/>)/gi;
  const videoReg = /(<video.*?)\<\/video>/gi;
  if (value.match(imgReg)) {
    value = changeImgurl(value);
  }
  if (value.match(videoReg)) {
    value = changeVideoUrl(value);
  }
  return value;
}

export function changeImgurl(value: string) {
  const result = value.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(
    match,
    capture
  ) {
    const ret = capture.replace("https://img.schtwz.cn/", "");
    const result = ret.slice(0, ret.indexOf("?"));
    return `<img src="${result}">`;
  });
  return result;
}

export function changeVideoUrl(value: string) {
  const result = value.replace(
    /<video [^>]*src=['"]([^'"]+).*?\<\/video>/gi,
    function(match, capture) {
      const ret = capture.replace("https://img.schtwz.cn/", "");
      const result = ret.slice(0, ret.indexOf("?"));
      return `<video src="${result}" controls="controls" width="100%" height="undefined" webkit-playsinline="true" playsinline="true" x5-playsinline="true"></video>`;
    }
  );
  return result;
}
  • c 端解析富文本地址
export function changeUrl(value: string) {
  if (typeof value != "string") return "";
  let result = value.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(
    match,
    capture
  ) {
    return `<img src="${signatureUrl(capture)}">`;
  });
  result = result.replace(
    /<video [^>]*src=['"]([^'"]+).*?\<\/video>/gi,
    function(match, capture) {
      // console.log(capture);
      return `<video src="${signatureUrl(
        capture
      )}" controls="controls" width="100%" height="undefined" webkit-playsinline="true" playsinline="true" x5-playsinline="true"></video>`;
    }
  );
  return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值