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
})
相关推荐
quitv13 分钟前
react脚手架配置别名
前端·javascript·react.js
Gazer_S2 小时前
【现代前端框架中本地图片资源的处理方案】
前端·javascript·chrome·缓存·前端框架
贺今宵4 小时前
通过$attrs传递的未指定名称的modelValue值在子组件中修改
前端·javascript
lifire_H8 小时前
Canvas在视频应用中的技术解析
前端·javascript·音视频
十八朵郁金香10 小时前
深入理解 JavaScript 中的 this 指向
开发语言·前端·javascript
贵州晓智信息科技10 小时前
使用 Three.js 转换 GLSL 粒子效果着色器
开发语言·javascript·着色器
linkcoco11 小时前
记录h5使用navigator.mediaDevices.getUserMedia录制音视频
前端·javascript·vue·音视频·js
Mh11 小时前
代码提交校验及提交规范的实践方案
前端·javascript·架构
昨日余光11 小时前
仅需三分钟,使用Vue3.x版本组件式风格实现一个消息提示组件!
前端·javascript·css·vue.js·typescript·html
软件开发技术深度爱好者11 小时前
验证码介绍及生成与验证(HTML + JavaScript实现)
javascript