WangEditor5-解析Word
WangEditor5-解析Word
wangEditor官网https://www.wangeditor.com/v5/toolbar-config.html
解析并不是全部解析,如字体颜色等信息会丢失yarn add @wangeditor/editor yarn add @wangeditor/editor-for-react # 用于解析Word yarn add mammoth
1、创建工具栏类
import { IButtonMenu, IDomEditor } from '@wangeditor/editor'; import { word } from '../icon'; class WordMenu implements IButtonMenu { title: string; tag: string; iconSvg: string; constructor() { this.title = '解析word到编辑器' // 自定义菜单标题 /** * 图标这里我的图标是在阿里妈妈适量图标库获取的https://www.iconfont.cn/ * 搜索对应的图标赋值svg代码放到方法返回即可 * icon/index.ts源码 * export const word = () => `<svg>...</svg>` */ this.iconSvg = word() // 图标 this.tag = 'button' } /** * 获取编辑器内容源码 * @param editor */ getValue(editor: IDomEditor): string | boolean { return false; } /** * 菜单是否需要激活,当切换为源码时菜单激活 * @param editor * @param active 激活状态 */ isActive(editor: IDomEditor, active?: boolean): boolean { return false; } /** * 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false * @param editor */ isDisabled(editor: IDomEditor): boolean { return false; } /** * 点击菜单时触发的函数 * @param editor * @param value */ exec(editor: IDomEditor, value: string | boolean) { if (this.isDisabled(editor)) return editor.emit('clickWord'); } } export default WordMenu;
2、工具栏方法实现
import mammoth from "mammoth"; import WordMenu from "./word"; /** * 解析word为html * @param file */ export const analysisWord = (file: any): Promise<string> => { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = (evt: any) => { mammoth .convertToHtml({arrayBuffer: evt.target.result, buffer: undefined, path: ""}) .then((res) => { resolve(res.value); }); } // 启动读取指定的 Blob 或 File 内容 reader.readAsArrayBuffer(file); }); } export const wordConf = { // 工具栏中的唯一key key: 'word', // 组件 factory: () => new WordMenu() };
3、页面具体代码
在组件初始化时注册
上传需要触发文件选择,所以给一个input type='file’隐藏起来
点击导入word时触发选择
import { IDomEditor, Boot } from '@wangeditor/editor'; import { Editor, Toolbar } from '@wangeditor/editor-for-react'; import '@wangeditor/editor/dist/css/style.css'; import React, {useEffect, useState, useRef} from 'react'; import {analysisWord, wordConf} from "./props"; const WangEditor = ({ value = '', mode = 'default', onChange, toolbarConfig = {} }: any) => { /***********自定义变量-------开始*************/ // editor 实例 const [editor, setEditor] = useState<IDomEditor | null>(null); // 编辑器内容 const [html, setHtml] = useState<string>(value || ''); const file = useRef<HTMLInputElement>(null); /***********自定义变量-------结束*************/ /***********生命周期函数-------开始*************/ // 及时销毁 editor useEffect(() => { if (editor?.isFocused()) { editor?.blur(); } return () => { // eslint-disable-next-line eqeqeq if (editor == null) return; editor.destroy(); setEditor(null); }; }, [editor]); const onCreated = (editor: IDomEditor) => { /* * 在组件创建时初始化注册菜单,注意菜单不可以重复注册否则会报异常 * Unhandled Rejection (Error): Duplicated key 'source' in menu items */ if (!editor.getAllMenuKeys().includes('word')) { Boot.registerMenu(wordConf); } setEditor(editor); // 监听点击word事件 editor?.on('clickWord', () => { // 开启进度条 editor.showProgressBar(20) // 选择文件 file.current?.click(); }); } /** * 文件上传回调,解析word * @param event 文件对象 */ const handleChange = async (event: any) => { const res = await analysisWord(event.target.files[0]); // 这里直接插入即可 editor?.dangerouslyInsertHtml(res); // 进度条借宿 editor?.showProgressBar(100); // 将文件上传框value给情况 event.target.value = ''; } /***********生命周期函数-------结束*************/ return ( <div> <input type='file' accept='.doc,.docx' ref={file} onChange={handleChange} style={{ display: "none" }}/> <Toolbar editor={editor} defaultConfig={{ ...toolbarConfig, // 添加自定义菜单 insertKeys: { index: editor?.getAllMenuKeys().length || 0, keys: ['word'], } }} mode={mode} /> <Editor value={html} onCreated={onCreated} /> </div> ); }; export default WangEditor;
效果:https://blog.csdn.net/Ajie246862/article/details/132624660