🟢 wangeditor 富文本
一款开源 Web 富文本编辑器,开箱即用,配置简单
wangedito 官网
- 简洁易用、功能强大、文档教程丰富
- 支持 JS、Vue、React
- 踩过 5000+坑
- 兼容主流的 PC 游览器、但不在支持 IE 游览器和移动端编辑
优势
- 使用 vdom
- 扩展性
- 中文文档
- 使用主流技术
- 及时反馈和沟通、有完整的社区
- 方便的应用于 Vue React
- 集成所有功能,无需二次开发
- 持续更新
⭐️安装 wangeditor
yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save
yarn add @wangeditor/editor-for-vue
# 或者 npm install @wangeditor/editor-for-vue --save
⭐️demo 模板
<template>
<div class="main">
<h1 class="title">wangeditor编辑器配置</h1>
<div style="border: 1px solid #ccc">
<Toolbar
:defaultConfig="toolbarConfig"
:editor="editor"
:mode="mode"
style="border-bottom: 1px solid #ccc"
/>
<Editor
v-model="html"
:defaultConfig="editorConfig"
:mode="mode"
class="editor"
style="height: 500px; overflow-y: hidden"
@onCreated="onCreated"
@onChange="onChange"
@onDestroyed="onDestroyed"
@onFocus="onFocus"
@onBlur="onBlur"
@customPaste="customPaste"
/>
</div>
<div class="sub-btn-box">
<el-button class="sub-btn" type="primary" @click="submit" plain
>提交</el-button
>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { DomEditor } from '@wangeditor/editor'
export default Vue.extend({
name: 'MyEditor',
components: { Editor, Toolbar },
data() {
return {
editor: null, // 编辑器实例
html: '<p>123</p>', // 实例文本
toolbarConfig: {
// 工具栏配置
// toolbarKeys: [
// // 分割线
// "|",
// // 菜单 key
// "bold", // 粗体
// "underline", // 下划线
// "italic", // 斜体
// "through", // 删除线
// "code", // 行内代码
// "sub", // 下标
// "sup", // 上标
// "clearStyle", // 清除格式
// "color", // 字体颜色
// "bgColor", // 背景色
// "fontSize", // 字号
// "fontFamily", // 字体
// "indent", // 增加缩进
// "delIndent", // 减少缩进
// "justifyLeft", // 左对齐
// "justifyRight", // 右对齐
// "justifyCenter", // 居中对齐
// "justifyJustify", // 两端对齐
// "lineHeight", // 行高
// "insertImage", // 网络图片
// "deleteImage", // 删除图片
// "editImage", // 编辑图片
// "viewImageLink", // 查看链接
// "imageWidth30", // 图片宽度相对于编辑器宽度的百分比30
// "imageWidth50", // 图片宽度相对于编辑器宽度的百分比50
// "imageWidth100", // 图片宽度相对于编辑器宽度的百分比100
// "divider", // 分割线
// "emotion", // 表情
// "insertLink", // 插入链接
// "editLink", // 修改链接
// "unLink", // 取消链接
// "viewLink", // 查看链接
// "codeBlock", // 代码块
// "blockquote", // 引用
// "headerSelect", // 标题
// "header1", // 标题1
// "header2", // 标题2
// "header3", // 标题3
// "header4", // 标题4
// "header5", // 标题5
// "todo", // 待办
// "redo", // 重做
// "undo", // 撤销
// "fullScreen", // 全屏
// "enter", // 回车
// "bulletedList", // 无序列表
// "numberedList", // 有序列表
// "insertTable", // 插入表格
// "deleteTable", // 删除表格
// "insertTableRow", // 插入行
// "deleteTableRow", // 删除行
// "insertTableCol", // 插入列
// "deleteTableCol", // 删除列
// "tableHeader", // 表头
// "tableFullWidth", // 宽度自适应
// "insertVideo", // 插入网络视频
// "uploadVideo", // 上传视频
// "editVideoSize", // 修改视频尺寸
// "uploadImage", // 上传图片
// "codeSelectLang", // 选择语言
// // 菜单组,包含多个菜单
// {
// key: "group-more-style", // 必填,要以 group 开头
// title: "更多样式", // 必填
// iconSvg: "<svg>....</svg>", // 可选
// menuKeys: ["through", "code", "clearStyle"], // 下级菜单 key ,必填
// },
// ], //重新配置工具栏,显示哪些菜单,以及菜单的排序、分组。
},
editorConfig: {
// 编辑器配置
placeholder: '请输入内容...', //提示信息
readOnly: false, //配置编辑器是否只读,默认为
autoFocus: true, //配置编辑器默认是否 focus 选中,默认为 true
scroll: false, //配置编辑器是否支持滚动,默认为 true 。注意,此时不要固定 editor-container 的高度,设置一个 min-height 即可。
// maxLength: 10, //配置编辑器的maxlength
MENU_CONF: {
// 文字颜色
color: {
// colors: ["#000", "#333", "#666"],//可选项
},
// 背景色
bgColor: {
// colors: ["#000", "#333", "#666"], //可选项
},
// 字号
fontSize: {
// fontSizeList: [
// // 元素支持两种形式
// // 1. 字符串;
// // 2. { name: 'xxx', value: 'xxx' }
// "12px",
// "16px",
// { name: "24px", value: "24px" },
// "40px",
// ],//可选项
},
// 字体
fontFamily: {
// fontFamilyList: [
// // 元素支持两种形式
// // 1. 字符串;
// // 2. { name: 'xxx', value: 'xxx' }
// "黑体",
// "楷体",
// { name: "仿宋", value: "仿宋" },
// "Arial",
// "Tahoma",
// "Verdana",
// ],//可选项
},
// 行号
lineHeight: {
// lineHeightList: ["1", "1.5", "2", "2.5"],//行高
},
// 标签
emotion: {
// emotions: "😀 😃 😄 😁 😆 😅 😂 🤣 😊 😇 🙂 🙃 😉".split(" "), // 数组可选项
},
// 上传图片的配置
uploadImage: {
// server服务端地址
server: '/api/upload', //必填,否则上传图片会报错
// fieldName文件名称默认值 'wangeditor-uploaded-image'
fieldName: 'your-custom-name',
// maxFileSize单个文件的最大体积限制,默认为 2M
maxFileSize: 1 * 1024 * 1024, // 1M
//maxNumberOfFiles 最多可上传几个文件,默认为 100
maxNumberOfFiles: 10,
// allowedFileTypes选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
allowedFileTypes: ['image/*'],
// meta自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
meta: {
token: 'xxx',
otherKey: 'yyy',
},
// metaWithUrl将 meta 拼接到 url 参数中,默认 false
metaWithUrl: false,
// headers自定义增加 http header
headers: {
Accept: 'text/x-json',
otherKey: 'xxx',
},
// withCredentials跨域是否传递 cookie ,默认为 false
withCredentials: true,
// timeout超时时间,默认为 10 秒
timeout: 5 * 1000, // 5 秒
// 下面是一些上传图片的回调函数
//onBeforeUpload 上传之前触发
onBeforeUpload(file) {
// JS 语法
// onBeforeUpload(file: File) { // TS 语法
// file 选中的文件,格式如 { key: file }
return file
// 可以 return
// 1. return file 或者 new 一个 file ,接下来将上传
// 2. return false ,不上传这个 file
},
// onProgress上传进度的回调函数
onProgress(progress) {
// JS 语法
// onProgress(progress: number) { // TS 语法
// progress 是 0-100 的数字
console.log('progress', progress)
},
// onSuccess单个文件上传成功之后
onSuccess(file, res) {
// JS 语法
// onSuccess(file: File, res: any) { // TS 语法
console.log(`${file.name} 上传成功`, res)
},
// onFailed单个文件上传失败
onFailed(file, res) {
// JS 语法
// onFailed(file: File, res: any) {
// TS 语法
console.log(`${file.name} 上传失败`, res)
},
// onError上传错误,或者触发 timeout 超时
onError(file, err, res) {
// JS 语法
// onError(file: File, err: any, res: any) {
// TS 语法
console.log(`${file.name} 上传出错`, err, res)
},
/**
* 自定义插入
* 如果你的服务端 response body 无法按照上文规定的格式,则无法插入图片,提示失败。但你可以使用 customInsert 来自定义插入图片。
*/
customInsert(res, insertFn) {
// JS 语法
// customInsert(res: any, insertFn: InsertFnType) { // TS 语法
// res 即服务端的返回结果
// 从 res 中找到 url alt href ,然后插入图片
insertFn(url, alt, href)
},
/**
* 自定义上传
* 如果你不想使用 wangEditor 自带的上传功能,例如你要上传到阿里云 OSS 。可以通过 customUpload 来自定义上传。
*/
customBrowseAndUpload(insertFn) {
// JS 语法
// customBrowseAndUpload(insertFn: InsertFnType) { // TS 语法
// 自己选择文件
// 自己上传文件,并得到图片 url alt href
// 最后插入图片
insertFn(url, alt, href)
},
// 小于该值就插入 base64 格式(而不上传),默认为 0
base64LimitSize: 5 * 1024, // 5kb
},
// 上传视频配置
uploadVideo: {
// 上传视频的配置比较复杂
// server服务端地址
server: '/api/upload', //必填,否则上传图片会报错
// form-data fieldName ,默认值 'wangeditor-uploaded-video'
fieldName: 'your-custom-name',
//maxFileSize 单个文件的最大体积限制,默认为 10M
maxFileSize: 5 * 1024 * 1024, // 5M
// maxNumberOfFiles最多可上传几个文件,默认为 5
maxNumberOfFiles: 3,
// allowedFileTypes选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
allowedFileTypes: ['video/*'],
// meta自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
meta: {
token: 'xxx',
otherKey: 'yyy',
},
// metaWithUrl将 meta 拼接到 url 参数中,默认 false
metaWithUrl: false,
// headers自定义增加 http header
headers: {
Accept: 'text/x-json',
otherKey: 'xxx',
},
// withCredentials跨域是否传递 cookie ,默认为 false
withCredentials: true,
// timeout超时时间,默认为 30 秒
timeout: 15 * 1000, // 15 秒
// 视频不支持 base64 格式插入
// 回调函数
// onBeforeUpload上传之前触发
onBeforeUpload(file) {
// JS 语法
// onBeforeUpload(file: File) {
// TS 语法
// file 选中的文件,格式如 { key: file }
return file
// 可以 return
// 1. return file 或者 new 一个 file ,接下来将上传
// 2. return false ,不上传这个 file
},
// onProgress上传进度的回调函数
onProgress(progress) {
// JS 语法
// onProgress(progress: number) {
// TS 语法
// progress 是 0-100 的数字
console.log('progress', progress)
},
// onSuccess单个文件上传成功之后
onSuccess(file, res) {
// JS 语法
// onSuccess(file: File, res: any) {
// TS 语法
console.log(`${file.name} 上传成功`, res)
},
// onFailed单个文件上传失败
onFailed(file, res) {
// JS 语法
// onFailed(file: File, res: any) {
// TS 语法
console.log(`${file.name} 上传失败`, res)
},
// onError上传错误,或者触发 timeout 超时
onError(file, err, res) {
// JS 语法
// onError(file: File, err: any, res: any) { // TS 语法
console.log(`${file.name} 上传出错`, err, res)
},
/**
* 自定义插入视频
* 如果你的服务端 response body 无法按照上文规定的格式,则无法插入视频,提示失败。
但你可以使用 customInsert 来自定义插入视频。
*/
customInsert(res, insertFn) {
// JS 语法
// customInsert(res: any, insertFn: InsertFnType) { // TS 语法
// res 即服务端的返回结果
// 从 res 中找到 url poster ,然后插入视频
insertFn(url, poster)
},
/**
* 自定义上传
* 如果你不想使用 wangEditor 自带的上传功能,例如你要上传到阿里云 OSS 。
可以通过 customUpload 来自定义上传。
*/
async customUpload(file, insertFn) {
// JS 语法
// customUpload(file: File, insertFn: InsertFnType) { // TS 语法
// file 即选中的文件
// 自己实现上传,并得到视频 url poster
// 最后插入视频
insertFn(url, poster)
},
/**
* 自定义选择视频
* 如果你不想使用 wangEditor 自带的选择文件功能,例如你有自己的图床,或者视频文件选择器。可以通过 customBrowseAndUpload 来自己实现选择视频、上传视频,并插入视频。
*/
customBrowseAndUpload(insertFn) {
// JS 语法
// customBrowseAndUpload(insertFn: InsertFnType) { // TS 语法
// 自己选择文件
// 自己上传文件,并得到视频 url poster
// 最后插入视频
insertFn(url, poster)
},
},
// 代码高亮
codeSelectLang: {
// 代码语言
codeLangs: [
{ text: 'CSS', value: 'css' },
{ text: 'HTML', value: 'html' },
{ text: 'XML', value: 'xml' },
// 其他
],
},
},
},
mode: 'default', // or 'simple'
}
},
methods: {
// 提交按钮点击事件
submit() {
console.log(`编辑器内容`, this.html)
console.log(`获取内容JSON`, this.editor.children)
console.log(`显示HTML`, this.editor.getHtml())
console.log(`显示Text`, this.editor.getText())
},
// onCreated编辑器创建完成的回调函数
onCreated(editor) {
this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
console.log('editor实例', this.editor)
},
// onChange编辑器内容、选区变化时的回调函数。
onChange(editor) {
console.log('onChange', editor)
// console.log("content", editor.children);
},
// 编辑器 focus 时的回调函数。
onFocus(editor) {
console.log('onFocus', editor)
},
// 编辑器 blur 时的回调函数。
onBlur(editor) {
console.log('onBlur', editor)
},
// 编辑器销毁时的回调函数。
onDestroyed(editor) {
console.log('onDestroyed', editor)
},
// 自定义粘贴,可阻止编辑器的默认粘贴,实现自己的粘贴逻辑。
customPaste(editor, event) {
// event 是 ClipboardEvent 类型,可以拿到粘贴的数据
// 可参考 https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardEvent
// const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
// const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
// const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
// 同步
editor.insertText('粘贴内容后、我会同步执行')
// 异步
setTimeout(() => {
editor.insertText('粘贴内容后、我会异步执行')
}, 1000)
// 阻止默认的粘贴行为
event.preventDefault()
return false
// 继续执行默认的粘贴行为
// return true
},
},
mounted() {
// 模拟 ajax 请求,异步渲染编辑器
setTimeout(() => {
// this.html = "<p'>模拟 Ajax 异步设置内容 HTML</p>";
this.html =
'<h1>模拟 Ajax 异步设置内容 HTML</h1><div data-w-e-type="todo"><input type="checkbox" disabled >代办1</div><div data-w-e-type="todo"><input type="checkbox" disabled checked>代办2</div><hr/><blockquote><span style="font-size: 22px;">🤑👌😚😀😃👌👆<br>1121</span><span style="font-size: 22px;"><sup>2123</sup></span><span style="font-size: 22px;">.<br></span><span style="font-size: 22px;"><strong>测试</strong></span><span style="font-size: 22px;"><br></span><span style="font-size: 22px;"><em>测试</em></span><span style="font-size: 22px;"><br></span><span style="font-size: 22px;"><em>测试123.</em></span><span style="font-size: 22px;"><br></span></blockquote>'
}, 500)
},
created() {},
beforeDestroy() {
const editor = this.editor
if (editor == null) return
editor.destroy() // 组件销毁时,及时销毁编辑器
},
})
</script>
<!--引入css样式-->
<style src="@wangeditor/editor/dist/css/style.css"></style>
<!--根据项目UI需求配置自己的css-->
<style lang="scss">
.main {
width: 80%;
height: 100%;
margin: 0 auto;
.title {
font-size: 20px;
text-align: center;
margin-bottom: 10px;
}
.sub-btn-box {
margin-top: 10px;
text-align: center;
}
.editor {
// height: 200px !important;
height: 700px !important;
#w-e-textarea-1 {
text-align: left !important;
}
.w-e-text-container {
text-align: left !important;
}
}
}
</style>
⭐️效果图
✒️总结
如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对前端端或者对python感兴趣的朋友,请多多关注💖💖💖,咱们一起探讨和努力!!!
👨🔧 个人主页 : 前端初见