React中使用Vditor详解

安装

npm install vditor -s

引用

导入依赖包

import Vditor from “vditor”;

导入样式

import “vditor/src/assets/scss/index.scss”;

使用示例

export default class Vditor extends Component {
  constructor(props) {
      super(props);
      this.state = {
        editValue: ""
      };
  }
  componentDidMount = () => {
    //组件挂载完成之后调用 注意一定要在组件挂载完成之后调用 否则会找不到注入的DOM
    this.createVidtor({ value: this.state.editValue });
  }
  //创建编辑器 下面会详解
  createVidtor = params => {
      let { value } = params;
      value = value ? value : " ";
      let that = this;
      const vditor = new Vditor("vditor", {
          height: 800,
          mode: "ir", //及时渲染模式
          placeholder: "React Vditor",
          toolbar: [
              "emoji",
              "headings",
              "bold",
              "italic",
              "strike",
              "link",
              "|",
              "list",
              "ordered-list",
              "check",
              "outdent",
              "indent",
              "|",
              "quote",
              "line",
              "code",
              "inline-code",
              "insert-before",
              "insert-after",
              "|",
              "upload",
              "table",
              "|",
              "undo",
              "redo",
              "|",
              "fullscreen",
              "edit-mode",
              {
                  name: "more",
                  toolbar: [
                      "both",
                      "code-theme",
                      "content-theme",
                      "export",
                      "outline",
                      "preview",
                      "devtools",
                      "info",
                      "help"
                  ]
              },
              "|",
              {
                  hotkey: "⌘-S",
                  name: "save",
                  tipPosition: "s",
                  tip: "保存",
                  className: "right",
                  icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/save.svg'/>`,
                  click() {
                      that.saveDoc();
                  }
              },
              {
                  hotkey: "",
                  name: "publish",
                  tipPosition: "s",
                  tip: "发布文章",
                  className: "right",
                  icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/publish.svg'/>`,
                  click() {
                      that.publishDoc();
                  }
              }
          ],
          after() {
              vditor.setValue(value);
          },
          blur() {
              that.saveDoc();
          },
          upload: {
              accept: "image/*",
              multiple: false,
              filename(name) {
                  return name
                      .replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, "")
                      .replace(/[\?\\/:|<>\*\[\]\(\)\$%\{\}@~]/g, "")
                      .replace("/\\s/g", "");
              },
              handler(files) {
                  function callback(path) {
                      let name = files[0] && files[0].name;
                      let succFileText = "";
                      if (vditor && vditor.vditor.currentMode === "wysiwyg") {
                          succFileText += `\n <img alt=${name} src="${path}">`;
                      } else {
                          succFileText += `  \n![${name}](${path})`;
                      }
                      document.execCommand("insertHTML", false, succFileText);
                  }
                  that.handleImageUpload(files, callback);
              },
              url(files) {
                  that.handleImageUpload(files);
              }
          }
      });
      this.vditor = vditor;
      return vditor;
  };
  //首先需要在render里面注入DOM,可自定义注入DOM的ID,初始化编辑器的时候使用自定义的ID即可
  render() {
    <div className="editorWrap">
        <div id="vditor" />
    </div>
  }
}

示例:

image-20201224175738268

功能使用

新建对象

const vditor = new Vditor("vditor", ...option);

新建对象时第一个参数ID,要对应上再render里面注入的ID

option参数

tip:只列举一下常用参数,其他的参数请参照官方API

参数 说明
height 配置编辑器高度
mode 编辑器模式
wysiwyg:所见即所得2
ir:及时渲染
sv:分屏模式
placeholder 占位符
toolbar 工具栏

Tip:如果要自定义工具栏的话,一定要加上默认的工具栏,不然只展示自定义的了

默认工具栏

tip:此为源码里面copy 不用更改可直接使用,官方已定义好了快捷键和功能

toolbar: [
            "emoji",
            "headings",
            "bold",
            "italic",
            "strike",
            "link",
            "|",
            "list",
            "ordered-list",
            "check",
            "outdent",
            "indent",
            "|",
            "quote",
            "line",
            "code",
            "inline-code",
            "insert-before",
            "insert-after",
            "|",
            "upload",
            "record",
            "table",
            "|",
            "undo",
            "redo",
            "|",
            "fullscreen",
            "edit-mode",
            {
                name: "more",
                toolbar: [
                    "both",
                    "code-theme",
                    "content-theme",
                    "export",
                    "outline",
                    "preview",
                    "devtools",
                    "info",
                    "help",
                ],
            }]

对应工具栏展示:

image-20201224173651841

自定义按钮

let that = this;
const vditor = new Vditor("vditor", {
    toolbar: [
        {
            hotkey: "⌘-S",
            name: "save",
            tipPosition: "s",
            tip: "保存",
            className: "right",
            icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/save.svg'/>`,
            click() {
                that.saveDoc();
            }
        },
        {
            hotkey: "",
            name: "publish",
            tipPosition: "s",
            tip: "发布文章",
            className: "right",
            icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/publish.svg'/>`,
            click() {
                that.publishDoc();
            }
        }
    ]
});
//tip:在调用本类封装的方法时提前把this赋值给其他方法内的变量,在Vditor内部改变了this指向
参数 说明
hotkey 热键配置
name 功能区分(唯一性)
tip 悬浮提示
className UI展示 right靠右
icon 按钮图标
click 点击事件

示例:

image-20201224175653047

获取值

saveDoc = () => {
  //在初始化时已经把vditor赋值到this对象上 可直接通过getValue方法获取当前编辑器的值
    let mdValue = this.vditor && this.vditor.getValue();
  //获取完值业务保存就行 这里不再详细写本人的保存方法了
  ...
}

赋值

let { value } = params;
value = value ? value : " ";
//如果是空值的话 最好给一个空格 以免编辑器初始化时报错
const vditor = new Vditor("vditor", {
  // value: value,
  after() {
      vditor.setValue(value);
  }
});
//tip:虽说官方也提供value直接赋值 但是在React里面不生效,就需要在after里面去调用setValue来完成赋值

自定义图片上传

const vditor = new Vditor("vditor", {
  upload: {
      accept: "image/*",
      multiple: false,
      filename(name) {
          return name
              .replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, "")
              .replace(/[\?\\/:|<>\*\[\]\(\)\$%\{\}@~]/g, "")
              .replace("/\\s/g", "");
      },
      handler(files) {
          function callback(path) {
              let name = files[0] && files[0].name;
              let succFileText = "";
              if (vditor && vditor.vditor.currentMode === "wysiwyg") {
                  succFileText += `\n <img alt=${name} src="${path}">`;
              } else {
                  succFileText += `  \n![${name}](${path})`;
              }
              document.execCommand("insertHTML", false, succFileText);
          }
          that.handleImageUpload(files, callback);
      },
      url(files, callback) {
          that.handleImageUpload(files, callback);
      }
  }
});
//此接口里面调用的是自己的图片上传 业务方自行实现
handleImageUpload = (file, callback) => {
    const reader = new FileReader();
    let formdata = new FormData();
    formdata.append("files", file[0]);
    reader.onload = () => {
        // setTimeout 模拟异步上传图片
        // 当异步上传获取图片地址后,执行callback回调(参数为imageUrl字符串),即可将图片地址写入markdown
        new Promise(resolve => {
            this.props.dispatch({
                type: "docManager/imageUpload",
                payload: { resolve, username: myInfo.userId, formdata }
            });
        }).then(res => {
            let imgurl = res.result.path;
            callback(imgurl);
        });
    };
    reader.readAsDataURL(file[0]);
};
参数 说明
accept 接收文件类型(我这边只做了图片上传)
multiple 是否多选
filename 格式化文件名
handler 点击数触发方法
url 配置此方法时可实现图片粘贴并上传

图片粘贴时读取的文件

image-20201224185044916

上传完成后接口返回的CDN地址

image-20201224190546200

上传完成后处理

handler(files) {
    function callback(path) {
        let name = files[0] && files[0].name;
        let succFileText = "";
        //上传完成获取当前编辑器模式 根据不同模式拼接不同的展示标签
        if (vditor && vditor.vditor.currentMode === "wysiwyg") {
            succFileText += `\n <img alt=${name} src="${path}">`;
        } else {
            succFileText += `  \n![${name}](${path})`;
        }
        //拼接完直接插入到鼠标选中位置
        document.execCommand("insertHTML", false, succFileText);
    }
    that.handleImageUpload(files, callback);
}

image-20201224190854846

总结

以上是本人在接入vditor编辑器是的一些使用总结,如果您还有什么更高级的定制玩法,可留言。


   转载规则


《React中使用Vditor详解》 浅夏晴空 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
基于源码剖析nodejs模块系统 基于源码剖析nodejs模块系统
nodejs模块系统简介为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。 模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之, 一个 Node.js 文件就是一个模块,这个文件可
2020-12-25
下一篇 
Android实现0.5像素线条 Android实现0.5像素线条
由于安卓手机无法识别border: 0.5px,因此我们要用0.5px的话必须要借助css3中的-webkit-transform:scale缩放来实现。 原理:将伪元素的宽设为200%,height设为1px通过-webkit-trans
2020-12-02
  目录