wangEditor v4的简单使用

当前文档是 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://www.mfbz.cn/a/366404.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

apache web服务内存泄露解决

文章目录 apache web服务内存泄露解决问题根源问题解决 apache web服务内存泄露解决 问题根源 apache在使用过程中&#xff0c;内存在逐步增长&#xff0c;重启服务后也没有用&#xff0c;经过多方资料排查由于是MaxRequestsPerChild配置引起的&#xff0c;注意apache2.4系列改…

有趣的CSS - 输入框选中交互动效

页面效果 此效果主要使用 css 伪选择器配合 html5 required 属性来实现一个简单的输入框的交互效果。 此效果可适用于登录页入口、小表单提交等页面&#xff0c;增强用户实时交互体验。 核心代码部分&#xff0c;简要说明了写法思路&#xff1b;完整代码在最后&#xff0c;可直…

MySQL 索引和事务

目录 1 索引1.1 简介1.2 使用1.3 示例 2 事务2.1 简介2.2 使用 1 索引 1.1 简介 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现。 索引底层是…

代码随想录算法训练营第二十四天|● 理论基础 ● 77. 组合

仅做学习笔记&#xff0c;详细请访问代码随想录 ● 理论基础 ● 77. 组合 ● 理论基础 回溯法解决的问题 回溯法&#xff0c;一般可以解决如下几种问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合 切割问题&#xff1a;一个字符串按一定规则有几…

【JavaEE进阶】 图书管理系统开发日记——叁

&#x1f334;前言 在前面我们实现了用户登录的接口。现在我们来实现图书列表展示页面。 &#x1f38b;数据准备 创建图书表&#xff0c;并初始化数据 -- 图书表 DROP TABLE IF EXISTS book_info; CREATE TABLE book_info (id INT ( 11 ) NOT NULL AUTO_INCREMENT,book_nam…

通用缓存SpringCache

概述 在项目中&#xff0c;我们通常会把高频的查询进行缓存。如资讯网站首页的文章列表、电商网站首页的商品列表、微博等社交媒体热搜的文章等等&#xff0c;当大量的用户发起查询时&#xff0c;借助缓存提高查询效率&#xff0c;同时减轻数据库压力。 目前的缓存框架有很多:…

银行数据仓库体系实践(16)--数据应用之财务分析

总账系统 在所有公司中&#xff0c;财务分析的基础都是核算&#xff0c;那在银行的系统体系中&#xff0c;核算功能在业务发生时由业务系统如核心、贷款、理财中实现登记&#xff0c;各业务系统会在每天切日后统计当天各机构的核算科目的发生额与余额&#xff0c;并统一送到总账…

基于SSM的个性化旅游攻略定制系统设计与实现(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的个性化旅游攻略定制系统设计与实现&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xf…

Google Play上架:因行为透明度被拒审或下架的政策自查(基于区块链的内容)

近期很多朋友的项目出现因行为透明度问题被谷歌拒审或者已经上架的包被下架甚至封号,今天解释一下为什么会被封号下架,根据是什么? 目录 政策发布时间与截止时间政策内容政策背景政策解析和问题讲解政策发布时间与截止时间 基于区块链的内容相关政策,于2023-07-12 公布,…

大数据 - Hadoop系列《三》- MapReduce(分布式计算引擎)概述

上一篇文章&#xff1a; 大数据 - Hadoop系列《三》- HDFS&#xff08;分布式文件系统&#xff09;概述-CSDN博客 目录 12.1 针对MapReduce的设计构思 1. 如何对付大数据处理场景 2. 构建抽象编程模型 3. 统一架构、隐藏底层细节 12.2 分布式计算概念 12.3 MapReduce定义…

最近nvm安装报错的原因找到了——npm原淘宝镜像正式到期!

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 背景 错误原因 问题排查 淘宝镜像 证书到期 问题解决 结语 背景 我们…

华为配置接口二三层切换示例

配置接口二三层切换示例 组网图形 图1 配置非自协商模式下速率和双工模式组网图 二三层切换简介配置注意事项组网需求配置思路操作步骤配置文件 二三层切换简介 基于接口板的硬件构造&#xff0c;某些形态设备上接口只能作为二层以太网接口&#xff0c;某些形态设备上接口…

炒黄金 vs 炒股:探寻投资路线的差异和各自的优势

在当前不景气的股市&#xff0c;人们越来越关注分散投资的方式&#xff0c;以期降低风险并稳定资产。炒黄金成为了一个备受关注的投资选择&#xff0c;与传统炒股相比&#xff0c;它到底有什么区别呢&#xff1f;本文将从多个维度深入分析这两种投资方式的差异以及各自的优势。…

红萝卜,咪咪甜,看斗看斗要过年

老了&#xff0c;老了&#xff0c;但少儿岁月唱过的川南儿歌&#xff0c;至今还能琅琅上口&#xff1a;“红萝卜&#xff0c;咪咪甜&#xff0c;看斗看斗要过年。” 2024年春节&#xff0c;眨眼工夫就要到来了。随着春运来临&#xff0c;人员流动增多&#xff0c; 呼吸道疾病的…

BetaFlight Current Calibration Guide

BetaFlight Current Calibration Guide Download link: BetaFlight_Current_Calibration_v2.xlsx This is a guide for how to use this xlsx file. If you want to know more about this file, please check BetaFlight开源代码之电流校准. Step 1 Filling Pre-Set-Scale, a…

Java/Python/Go不同开发语言基础数据结构和相关操作总结-Map篇

Java/Python/Go不同开发语言基础数据结构和相关操作总结 1. Java1.1 基础操作1.1.1 数据结构和定义方式1.1.2 增加1.1.3 修改1.1.4 查询1.1.5 删除1.1.6 获取总长度1.1.7 按key排序1.1.8 按value排序1.1.9 遍历 1.2 常用其他方法1.2.1 几种数据结构的对比 2. Go2.1基础操作2.1.…

ChatGPT实战100例 - (12) 结构化提示词 LangGPT 实战

文章目录 ChatGPT实战100例 - (12) 结构化提示词 LangGPT 实战一、LangGPT是什么?二、远古诗人 vs 现代诗人三、LangGPT Role模板实战 - 甩锅王Role模板特征提取四、 用AI实现提示词结构化ChatGPT实战100例 - (12) 结构化提示词 LangGPT 实战 一、LangGPT是什么? 随着大模型…

拓扑排序算法

操作对象&#xff1a;AOV网的点和边 有向无环图&#xff1a;有向图且不会形成回路 AOV网&#xff1a;在一个表示工程的有向图中&#xff0c;用顶点表示活动&#xff0c;用弧表示活动之间的优先关系&#xff0c;这样的有向图为顶点表示活动的网&#xff0c;称为AOV网 拓扑排序…

Python程序设计 函数基础

简单函数 函数&#xff1a;就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。 函数的使用包含两个步骤&#xff1a; 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用&#xff0c;在开发程序时&#xff0c;使用…

vue3.0中从proxy中取值

使用vue3.0时&#xff0c;因为底层是使用proxy进行代理的所以当我们打印一些值的时候是proxy代理之后的&#xff0c;是Proxy 对象&#xff0c;Proxy对象里边的[[Target]]才是真实的对象。也是我们需要的 第一种获取target值的方式&#xff1a; import { toRaw } from vue; le…
最新文章