第一步
先下载
npm install @wangeditor/editor @wangeditor/editor-for-vue
然后在项目中创建一个组件 如 test.vue
<template>
<div>
<div>
<button @click="printEditorHtml">print html</button>
<button @click="insertTextHandler">insert text</button>
<button @click="disableHandler">disable</button>
</div>
<div
class="editor-container"
:class="{ fullscreen: isFullscreen }"
style="border: 1px solid #ccc; margin-top: 10px"
>
<!-- 工具栏 -->
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:defaultConfig="toolbarConfig"
/>
<!-- 编辑器 -->
<Editor
style="height: 400px; overflow-y: hidden"
:defaultConfig="editorConfig"
v-model="html"
@onChange="onChange"
@onCreated="onCreated"
/>
</div>
</div>
</template>
<script>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
export default {
name: "MyEditor",
components: { Editor, Toolbar },
data() {
return {
editor: null,
html: "<p>hello world</p>",
isFullscreen: false, // 用于跟踪全屏状态
toolbarConfig: {
// toolbarKeys: [
// 'bold', 'italic', 'underline', 'menu1', 'uploadImage', 'uploadVideo' // 添加自定义的 uploadWord 按钮
// ]
},
editorConfig: {
placeholder: "请输入内容...",
// autoFocus: false,
MENU_CONF: {
uploadImage: {
customUpload: (resultFiles, insertImgFn) => {
const file = resultFiles[0];
const allowedFileTypes = [
"image/jpeg",
"image/png",
"image/gif",
"image/jpg",
"image/webp",
"image/svg",
];
const maxFileSize = 5 * 1024 * 1024; // 5MB
// 检查文件类型
if (!allowedFileTypes.includes(file.type)) {
alert("文件类型不支持,请上传图片文件。");
return;
}
// 检查文件大小
if (file.size > maxFileSize) {
alert("文件大小超出限制,请上传小于 5MB 的图片。");
return;
}
const formData = new FormData();
formData.append("file", file);
queryOperator(formData)
.then((response) => {
const url = response.data.url; // 根据你的接口返回结构调整
insertImgFn(url);
})
.catch((error) => {
console.error("图片上传失败", error);
});
},
maxFileSize: 5 * 1024 * 1024, // 5MB
maxNumberOfFiles: 5,
allowedFileTypes: [
"image/jpeg",
"image/png",
"image/gif",
"image/jpg",
"image/webp",
"image/svg",
], //允许上传的格式
},
uploadVideo: {
customUpload: (resultFiles, insertVideoFn) => {
const file = resultFiles[0];
const allowedFileTypes = [
"video/mp4",
"video/avi",
"video/wmv",
"video/flv",
"video/rmvb",
];
const maxFileSize = 10 * 1024 * 1024; // 10MB
// 检查文件类型
if (!allowedFileTypes.includes(file.type)) {
alert("文件类型不支持,请上传视频文件。");
return;
}
// 检查文件大小
if (file.size > maxFileSize) {
alert("文件大小超出限制,请上传小于 10MB 的视频。");
return;
}
const formData = new FormData();
formData.append("file", file);
queryOperator(formData)
.then((response) => {
const url = response.data.url; // 根据你的接口返回结构调整
insertVideoFn(url);
})
.catch((error) => {
console.error("视频上传失败", error);
});
},
maxFileSize: 10 * 1024 * 1024, // 10MB
allowedFileTypes: [
"video/mp4",
"video/avi",
"video/wmv",
"video/flv",
"video/rmvb",
],
},
},
},
};
},
methods: {
onCreated(editor) {
this.editor = Object.seal(editor); // 【注意】一定要用 Object.seal() 否则会报错
/*
这是针对于 自定义的功能的
let keysarr = ["menu1"]; //导入word的 自定义menu
if (true) {
keysarr.splice(1, 1, "btn1"); //预览的自定义button
}
// 注册自定义上传 Word 文件的处理逻辑
this.toolbarConfig.insertKeys = {
index: 32, // 插入的位置,基于当前的 toolbarKeys
keys: keysarr,
};
// 监听自定义上传事件
editor.on("upload-word-file", (file) => {
this.uploadWordFile(file, editor);
});
// 监听自定义上传事件
editor.on("btns", (bool) => {
if (bool) console.log("object");
});
**/
// 监听全屏事件
editor.on("fullscreen", (isFullscreen) => {
this.isFullscreen = isFullscreen;
});
},
//自定义上传的function
uploadWordFile(file, editor) {
const allowedFileTypes = [
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
];
const maxFileSize = 10 * 1024 * 1024; // 10MB
// 检查文件类型
if (!allowedFileTypes.includes(file.type)) {
alert("文件类型不支持,请上传 Word 文件(.doc, .docx)。");
return;
}
// 检查文件大小
if (file.size > maxFileSize) {
alert("文件大小超出限制,请上传小于 10MB 的 Word 文件。");
return;
}
console.log(file);
this.html = "<p>Ajax 异步设置内容 HTML-----文件删除</p>";
const formData = new FormData();
formData.append("qqfile", file);
// 自定义上传逻辑
},
onChange(editor) {
console.log("onChange", editor.getHtml()); // onChange 时获取编辑器最新内容
},
insertTextHandler() {
const editor = this.editor;
if (editor == null) return;
editor.insertText(" hello ");
},
printEditorHtml() {
const editor = this.editor;
if (editor == null) return;
console.log(editor.getHtml());
},
disableHandler() {
const editor = this.editor;
if (editor == null) return;
editor.disable();
},
},
beforeDestroy() {
const editor = this.editor;
if (editor == null) return;
editor.destroy(); // 组件销毁时,及时销毁 editor ,重要!!!
},
mounted() {
// 模拟 ajax 请求,异步渲染编辑器
// setTimeout(() => {
// this.html = "<p>Ajax 异步设置内容 HTML</p>";
// }, 1500);
},
};
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style scoped>
/* 全屏时的样式 */
.fullscreen ~ .other-elements {
display: none;
}
.editor-container.fullscreen {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
background: #fff;
}
</style>
第二步 (如果需要自定义一些功能) 在 utils文件夹 或者其他文件夹 创建 (自定义)coustomizer.js 和 setupWangEditor.js
coustomizer.js
export class MyModalMenu {
constructor() {
this.title = '导入Word'
this.tag = 'button'
this.showModal = true
this.modalWidth = 400
}
isActive(editor) {
return false
}
getValue(editor) {
return ''
}
isDisabled(editor) {
return false
}
exec(editor, value) { }
getModalPositionNode(editor) {
return null
}
getModalContentElem(editor) {
const content = document.createElement('div')
content.innerHTML = `
<div style="padding: 20px;">
<h3>导入Word文件</h3>
<input id="wordFileInput" type="file" accept=".doc, .docx" style="margin-bottom: 10px;" />
<div style="text-align: right;">
<button id="uploadBtn" class="el-button el-button--primary" style="margin-right: 10px;">确认导入</button>
<button id="cancelBtn" class="el-button">取消</button>
</div>
</div>
`
const uploadBtn = content.querySelector('#uploadBtn')
const cancelBtn = content.querySelector('#cancelBtn')
uploadBtn.onclick = () => {
const input = content.querySelector('#wordFileInput')
const file = input.files[0]
if (file) {
editor.emit('upload-word-file', file)
editor.hidePanelOrModal() // 关闭对话框
} else {
alert('请选择一个Word文件')
}
}
cancelBtn.onclick = () => {
editor.hidePanelOrModal() // 关闭对话框
}
return content
}
}
export class MyButtonMenu {
constructor() {
this.title = '预览' // 自定义菜单标题
// this.iconSvg = '<svg>...</svg>' // 可选
this.tag = 'button'
}
// 获取菜单执行时的 value ,用不到则返回空 字符串或 false
getValue(editor) {
return ' hello '
}
// 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
isActive(editor) {
return false
}
// 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
isDisabled(editor) {
return false
}
// 点击菜单时触发的函数
exec(editor, value) {
if (this.isDisabled(editor)) return
editor.emit('btns', true)
// editor.insertText(value) // value 即 this.value(editor) 的返回值
}
}
setupWangEditor.js
import { Boot } from '@wangeditor/editor'
import { MyModalMenu,MyButtonMenu } from "./zdy"
export function setupWangEditor() {
const menu1Conf = {
key: 'menu1', // 定义 menu key :要保证唯一、不重复(重要)
factory() {
return new MyModalMenu() // 使用自定义的菜单类
},
}
const btn1Conf = {
key: 'btn1', // 定义 menu key :要保证唯一、不重复(重要)
factory() {
return new MyButtonMenu() // 使用自定义的菜单类
},
}
const module = {
menus: [menu1Conf,btn1Conf],
}
Boot.registerModule(module)
}
然后在 main.js 里导入
import { setupWangEditor } from './utils/setupWangEditor' // 确保路径正确
// 设置 WangEditor
setupWangEditor();