wangEditor v4的简单使用

当前文档是 wangEditor v4 版本的。

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

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

介绍

English documentation

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

1:npm 安装 wangeditor

wangeditor v4 npm i wangeditor --save

基本使用:

javascript 复制代码
<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

javascript 复制代码
import E from 'wangeditor'

3:创建html

html 复制代码
<div ref="editorRef"></div>

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

javascript 复制代码
const editorRef = ref()
editor = new E(editorRef.value)

4:配置菜单

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

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

5:图片相关处理

5.1 上传图片限制

javascript 复制代码
editor.config.uploadImgMaxLength = 3

5.2 上传图片大小限制

javascript 复制代码
editor.config.uploadImgMaxSize: 10 * 1024 * 1024, // 10M

5.3 请求头的设置

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

5.4 上传请求接口

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

5.5 上传前的钩子函数

javascript 复制代码
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,按照官方文档写法如下:

javascript 复制代码
  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菜单添加事件

javascript 复制代码
// 菜单点击事件
clickHandler() {
   this.switchMode()
   this.tryChangeActive()
}

修改源码模式

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

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

在这里判断模式状态

javascript 复制代码
 this.mode = this.isSouceMode() ? Mode.Live : Mode.Source

重新设置编辑器内容

javascript 复制代码
let html = this.editor.txt.html() || ''

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

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

javascript 复制代码
html = html.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ /g, '&nbsp;')

源码转换为文本内容

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

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

javascript 复制代码
tryChangeActive() {
    if (this.isSouceMode()) {
      this.active()
    } else {
      this.unActive()
    }
  }

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

7:案例

扩展菜单class

javascript 复制代码
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配置

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

部分代码

javascript 复制代码
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
})
相关推荐
.生产的驴43 分钟前
React 页面路由ReactRouter 路由跳转 参数传递 路由配置 嵌套路由
前端·javascript·react.js·前端框架·json·ecmascript·html5
打小就很皮...1 小时前
PDF 下载弹窗 content 区域可行性方案
前端·javascript·pdf
孤狼warrior8 小时前
爬虫进阶 JS逆向基础超详细,解锁加密数据
javascript·爬虫
前端炒粉8 小时前
18.矩阵置零(原地算法)
javascript·线性代数·算法·矩阵
listhi5208 小时前
利用React Hooks简化状态管理
前端·javascript·react.js
华仔啊9 小时前
这个Vue3旋转菜单组件让项目颜值提升200%!支持多种主题,拿来即用
前端·javascript·css
CsharpDev-奶豆哥10 小时前
JavaScript性能优化实战大纲
开发语言·javascript·性能优化
yume_sibai13 小时前
TS 常用内置方法
前端·javascript·typescript
新知图书13 小时前
ArkTS语言、基本组成与数据类型
前端·javascript·typescript
西西学代码13 小时前
Flutter---个人信息(1)---实现简单的UI
开发语言·javascript·flutter