React中使用Vditor詳解(自定義圖片上傳)

安裝

npm install vditor -s

引用

導入依賴包css

import Vditor from "vditor";

導入樣式npm

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>
  }
}

示例: markdown

image-20201224175738268

功能使用

新建對象

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

新建對象時第一個參數ID,要對應上再render裏面注入的IDapp

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編輯器是的一些使用總結,若是您還有什麼更高級的定製玩法,可留言。svg

相關文章
相關標籤/搜索