wangEditor v4的简单使用

news/2024/7/5 2:24:55

当前文档是 wangEditor v4 版本的。

wangEditor v5 已经正式发布,可参考文档。

v5 发布之后,v4 将不再开发新功能。

介绍

English documentation

wangEditor4 —— 轻量级 web 富文本编辑器,配置方便,使用简单。

  • 官网:www.wangeditor.com
  • 文档:www.wangeditor.com/v4
  • 源码:github.com/wangeditor-team/wangEditor (欢迎 star)

1:npm 安装 wangeditor

wangeditor v4 npm i wangeditor --save

基本使用:

<div id="div1">
    <p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<script type="text/javascript">
    const E = window.wangEditor
    const editor = new E('#div1')
    editor.create()
</script>

2:构建引入 wangeditor

import E from 'wangeditor'

3:创建html

<div ref="editorRef"></div>

根据 ref 设置 编辑器元素高度,实例化 wangeditor

const editorRef = ref()
editor = new E(editorRef.value)

4:配置菜单

默认情况下,显示所有菜单

 // 配置菜单栏,删减菜单,调整顺序
editor.config.menus = [
    'bold',
    'head',
    'link',
    'italic',
    'underline'
]
​

5:图片相关处理

5.1 上传图片限制

editor.config.uploadImgMaxLength = 3

5.2 上传图片大小限制

editor.config.uploadImgMaxSize: 10 * 1024 * 1024, // 10M

5.3 请求头的设置

uploadImgServer: props.action, // 配置 server 接口地址
uploadImgHeaders: {
   Authorization: `Bearer ${getPiniaToken()}`,
   'X-Requested-With': 'XMLHttpRequest',
},

5.4 上传请求接口

editor.config.customUploadImg = function (resultFiles, insertImgFn) {
    // resultFiles 是 input 中选中的文件列表
    // insertImgFn 是获取图片 url 后,插入到编辑器的方法
​
    // 上传图片,返回结果,将图片插入到编辑器中
    insertImgFn(imgUrl)
}

5.5 上传前的钩子函数

editor.config.uploadImgHooks = {
    // 上传图片之前
    before: function(xhr) {
        console.log(xhr)
​
        // 可阻止图片上传
        return {
            prevent: true,
            msg: '需要提示给用户的错误信息'
        }
    },
    // 图片上传并返回了结果,图片插入已成功
    success: function(xhr) {
        console.log('success', xhr)
    },
    // 图片上传并返回了结果,但图片插入时出错了
    fail: function(xhr, editor, resData) {
        console.log('fail', resData)
    },
    // 上传图片出错,一般为 http 请求的错误
    error: function(xhr, editor, resData) {
        console.log('error', xhr, resData)
    },
    // 上传图片超时
    timeout: function(xhr) {
        console.log('timeout')
    },
    // 图片上传并返回了结果,想要自己把图片插入到编辑器中
    // 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式,可使用 customInsert
    customInsert: function(insertImgFn, result) {
        // result 即服务端返回的接口
        console.log('customInsert', result)
​
        // insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
        insertImgFn(result.data[0])
    }
}

如果使用了 customUploadImg 自定义上传事件,那么 wangeditor 其他的图片上传api将会失效,例如: uploadImgServeruploadImgHeadersuploadImgHooks

以上都是修改在 editor.config,可以直接在 定义一个对象在editor.config中,看自己的需求:

6:设置是否源码模式

wangeditor 4 不支持源码模式,但可以自定义新增菜单

wangeditor 中创建 dom,按照官方文档写法如下:

  constructor(editor: E) {
    // data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
    const $elem = $(`
      <div class="w-e-menu" data-title="源码">
        <i style="font-style: normal">源码</i>
      </div>`)
    super($elem, editor)
  }

给新增的dom菜单添加事件

// 菜单点击事件
clickHandler() {
   this.switchMode()
   this.tryChangeActive()
}

修改源码模式

enum Mode {
  // 源码模式
  Source = 'source',
  // 实时预览模式
  Live = 'live',
}

上面使用了枚举定义,也可以不需要做,看自己的使用方式

在这里判断模式状态

 this.mode = this.isSouceMode() ? Mode.Live : Mode.Source

重新设置编辑器内容

let html = this.editor.txt.html() || ''

切换为源码模式,替换内容

使用字符串replace()函数查找字符进行转换,输出为源码Html

html = html.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ /g, '&nbsp;')

源码转换为文本内容

 html = this.editor.txt
        .text()
        .replace(/&lt;/gi, '<')
        .replace(/&gt;/gi, '>')
        .replace(/&nbsp;/gi, ' ')

菜单激活事件,每次切换菜单的时候要调用下wangeditor 方法,否则编辑器不知道你当前菜单(扩展)有哪些

tryChangeActive() {
    if (this.isSouceMode()) {
      this.active()
    } else {
      this.unActive()
    }
  }

其他,扩展菜单可以参考文档案例:https://codepen.io/xiaokyo-the-bold/pen/ZEpWBeo

7:案例

扩展菜单class

export default class sourceMenu extends BtnMenu {
  mode = Mode.Live
​
  constructor(editor: E) {
    const $elem = $(`
      <div class="w-e-menu" data-title="源码">
        <i style="font-style: normal">源码</i>
      </div>`)
    super($elem, editor)
  }
​
  // 菜单点击事件
  clickHandler() {
    this.switchMode()
    this.tryChangeActive()
  }
    
  tryChangeActive() {
    if (this.isSouceMode()) {
      this.active()
    } else {
      this.unActive()
    }
  }
​
  isSouceMode() {
    return this.mode === Mode.Source
  }
​
  switchMode() {
    this.mode = this.isSouceMode() ? Mode.Live : Mode.Source
    let html = this.editor.txt.html() || ''
    if (this.isSouceMode()) {
      html = html.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ /g, '&nbsp;')
    } else :
      html = this.editor.txt
        .text()
        .replace(/&lt;/gi, '<')
        .replace(/&gt;/gi, '>')
        .replace(/&nbsp;/gi, ' ')
    }
    this.editor.txt.html(html)
  }
}

在页面加载时,初始化wangeditor配置

  editor.create()
  editor.txt.html(props.modelValue) // 初始化重新设置编辑器内容

部分代码

onMounted(() => {
  editor = new E(editorRef.value)
  // 扩展自定义【源码】菜单
  const sourceMenuKey = 'source'
  editor.menus.extend(sourceMenuKey, sourceMenu)
  // 配置
  Object.assign(editor.config, {
    zIndex: 1,
    focus: false,
    height: props.height,
    menus: [
      sourceMenuKey, // 源码菜单
      'head',
      'bold',
      'fontSize',
      'fontName',
      'italic',
      'underline',
      'strikeThrough',
      'indent',
      'lineHeight',
      'foreColor',
      'backColor',
      'link',
      'list',
      'todo',
      'justify',
      'quote',
      'emoticon',
      'image',
      // 'video', // 移除视频菜单
      'table',
      'code',
      'splitLine',
      'undo',
      'redo',
    ],
    uploadFileName: 'file',
    uploadImgParams: {
      path: props.path,
    },
    uploadImgServer: '', // 配置 server 接口地址
    uploadImgHeaders: {
      Authorization: 'token',
      'X-Requested-With': 'XMLHttpRequest',
    },
    // 限制上传的最大图片数量
    uploadImgMaxLength: 2,
    // 单个文件的最大体积限制,默认为 10M
    uploadImgMaxSize: 5 * 1024 * 1024, // 5M
    customUploadImg: (files: Blob[], insertImgFn: (path: string) => void) => {
      try {
        const imgData = new FormData()
        for (let i in files) {
          imgData.append(`file`, files[i])
        }
        // 请求接口,并通过   insertImgFn()函数 插入到编辑器中
        // imgUrl 是从接口返回的图片地址
            insertImgFn(imgUrl)
      } catch (error) {
        message.error('图片上传失败,请重新上传')
      }
    },
​
    uploadImgHooks: {
      customInsert: function (insertImgFn: (path: string) => void, res: Recordable) {
        // res即远程请求的response
        // insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
        insertImgFn(res.data.path as string)
      },
    },
    onchange() {
      let sourceMenu = editor?.menus.menuList.find((item) => item.key === sourceMenuKey)
      emit('update:isActive', sourceMenu?.isActive)
      emit('update:modelValue', editor!.txt.html())
    },
    onblur() {
      lock = true
    },
  })
  editor.create()
  editor.txt.html(‘回显时的内容’) // 初始化重新设置编辑器内容
  watchEffect(() => {
    props.disabled ? editor?.disable() : editor?.enable()
  })
})
onBeforeUnmount(() => {
  editor!.destroy()
  editor = null
})


http://lihuaxi.xjx100.cn/news/2008488.html

相关文章

jupyter设置环境变量

要在Jupyter中设置环境变量&#xff0c;可以按照以下方法之一进行操作&#xff1a; 1. 在Jupyter Notebook中设置环境变量&#xff1a; - 打开Jupyter Notebook。 - 创建一个新的或打开一个已有的Jupyter Notebook。 - 在Notebook的代码单元格中&#xff0c;使用%env…

C++类和对象入门(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、类的作用域 类定义了一个新的作用域&#xff0c;类的所有成员都在类的作用域中。在类体外定义成员时&#xff0c;需要…

程序员的悲哀:知名Python库requests作者失业了

在当今这个快速发展的科技时代&#xff0c;程序员作为创新的驱动力&#xff0c;一直被视为时代的宠儿。然而&#xff0c;即使在这样一个充满机会的领域&#xff0c;也有着不为人知的辛酸。近日&#xff0c;一个令人震惊的消息传遍了编程社区&#xff1a;知名Python库requests的…

Unity之第一人称角色控制

目录 第一人称角色控制 &#x1f634;1、准备工作 &#x1f4fa;2、鼠标控制摄像机视角 &#x1f3ae;3、角色控制 &#x1f603;4.杂谈 第一人称角色控制 专栏Unity之动画和角色控制-CSDN博客的这一篇也有讲到角色控制器&#xff0c;是第三人称视角的&#xff0c;以小编…

【PTA浙大版《C语言程序设计(第4版)》编程题】练习7-4 找出不是两个数组共有的元素(附测试点)

目录 输入格式: 输出格式: 输入样例: 输出样例: 代码呈现 测试点 给定两个整型数组&#xff0c;本题要求找出不是两者共有的元素。 输入格式: 输入分别在两行中给出两个整型数组&#xff0c;每行先给出正整数N&#xff08;≤20&#xff09;&#xff0c;随后是N个整数&a…

nodejs+vue企业公司设备维护报修管理系统6p9i9

为设计一个安全便捷&#xff0c;并且使用户更好获取工厂生产设备维护信息&#xff0c;本文主要有安全、简洁为理念&#xff0c;实现用户快捷寻找工厂生产设备维护信息&#xff0c;从而解决工厂生产设备维护信息复杂难辨的问题。该系统采用nodejs语言、vue框架和mysql数据库进行…

qt5-入门-信号槽理解+QMainWindow

参考&#xff1a; Qt 深入了解信号槽_w3cschool https://www.w3cschool.cn/learnroadqt/wz3t1j47.html Qt MainWindow_w3cschool https://www.w3cschool.cn/learnroadqt/uqjl1j4b.html 本地环境&#xff1a; win10专业版&#xff0c;64位 信号槽 最简单的例子&#xff1a;写一…

java并发执行批量插入

java并发执行批量插入 1、mybatis-plus批量插入 long start System.currentTimeMillis();int num 5000; //一次批量插入的数量int j 0;for (int i 0;i<20;i){List<User> userList new ArrayList<>();while (true){j;User user new User();user.setUserP…