安装依赖
wangeditor基于 slate 内核开发,但不依赖于 React ,所以它本身是无框架依赖的。并且,官方封装了 Vue React 组件,可以很方便的用于 Vue React 等框架。
wangeditor——dome
- 安装 editor
yarn add @wangeditor/editor#
或者 npm install @wangeditor/editor --save
- 安装 React 组件
yarn add @wangeditor/editor-for-react
或者 npm install @wangeditor/editor-for-react --save
组件效果图
封装 WangEditor组件
新建文件
WangEditor/index.tsx
/**
* index.tsx 文件
*/
import React, { useState, useEffect, useContext } from 'react';
import '@wangeditor/editor/dist/css/style.css';
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import { customUploadImg } from '@/pages/product/manager/services/list';
import hmltContext from './createContext';
type EditorProps = {
getHtmlContent: Function;
};
const WangEditor: React.FC<EditorProps> = props => {
console.log(props);
const { getHtmlContent } = props;
const [editor, setEditor] = useState(null); // 存储 editor 实例
const [html, setHtml] = useState('<p>请输入内容</p>');
// const count = useContext(hmltContext); // 得到父组件传的值
// 模拟 ajax 请求,异步设置 html
useEffect(() => {
setTimeout(() => {
setHtml('<p>请输入内容</p>');
}, 1500);
}, []);
useEffect(() => {
console.log(html, '----------');
getHtmlContent(html); // 向父组件传参
}, [html]);
const toolbarConfig = {};
const editorConfig = { MENU_CONF: {} };
editorConfig.placeholder = '请输入内容...';
editorConfig.MENU_CONF['uploadImage'] = {
server: `${process.env.BASE_FILE_SERVER}/upload`,
// 自定义增加 http header
// headers: {
// Accept: 'text/x-json',
// otherKey: 'xxx'
// },
// 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
meta: {
userName: 'yunjin_file_upload',
password: 'yunjin_upload_password',
domain: 'product',
secret: 'N',
},
// 单个文件的最大体积限制,默认为 2M
maxFileSize: 10 * 1024 * 1024, // 10M
// 最多可上传几个文件,默认为 100
maxNumberOfFiles: 10,
// 小于该值就插入 base64 格式(而不上传),默认为 0
//base64LimitSize: 5 * 1024 // 5kb
// 自定义插入图片
customInsert(res: any, insertFn: InsertFnType) {
// res 即服务端的返回结果
console.log(res, insertFn);
// 从 res 中找到 url alt href ,然后插图图片
insertFn(`/file${res.result.fileList[0].url}`);
},
// 跨域是否传递 cookie ,默认为 false
withCredentials: true,
// 超时时间,默认为 10 秒
timeout: 5 * 1000, // 5 秒
// 上传之前触发
onBeforeUpload(file) {
// file 选中的文件,格式如 { key: file }
return file
// 可以 return
// 1. return file 或者 new 一个 file ,接下来将上传
// 2. return false ,不上传这个 file
},
// 上传进度的回调函数
onProgress(progress: number) {
// progress 是 0-100 的数字
console.log('progress', progress)
},
// 单个文件上传成功之后
onSuccess(file: File, res: any) {
console.log(`${file.name} 上传成功`, res)
},
// 单个文件上传失败
onFailed(file: File, res: any) {
console.log(`${file.name} 上传失败`, res)
},
// 上传错误,或者触发 timeout 超时
onError(file: File, err: any, res: any) {
console.log(`${file.name} 上传出错`, err, res)
},
};
// 及时销毁 editor
useEffect(() => {
return () => {
if (editor == null) return;
editor.destroy();
setEditor(null);
};
}, [editor]);
// function insertText() {
// if (editor == null) return
// editor.insertText(' hello ')
// }
// function printHtml() {
// if (editor == null) return
// console.log(editor.getHtml())
// }
return (
<hmltContext.Provider value={html}>
>
{/* <div>
<button onClick={insertText}>insert text</button>
<button onClick={printHtml}>print html</button>
</div> */}
<div style={{ border: '1px solid #ccc', zIndex: 100, marginTop: '15px' }}>
<Toolbar
editor={editor}
defaultConfig={toolbarConfig}
mode="default"
style={{ borderBottom: '1px solid #ccc' }}
/>
<Editor
defaultConfig={editorConfig}
value={html}
onCreated={setEditor}
onChange={editor => setHtml(editor.getHtml())}
mode="default"
style={{ height: '500px' }}
/>
</div>
<div style={{ marginTop: '15px' }}>{html}</div>
</hmltContext.Provider>
);
};
export default WangEditor;
新建文件
WangEditor/createContext.tsx
// createContext.js文件
import { createContext } from "react";
const hmltContext = createContext(null);
export default hmltContext;
父组件使用
import React, { useState } from 'react';
import { connect } from 'dva';
const Comp: React.FC<CompProps> = ({ dispatch, loading, id }) => {
const [WangEditorUsageNotice, setWangEditorUsageNotice] = useState('');
return (
<div >
<Form.Item
labelCol={{ span: 4 }}
wrapperCol={{ span: 15 }}
label="使用须知"
>
<WangEditor getHtmlContent={setWangEditorUsageNotice}/>
</Form.Item>
</div>
);
};
export default connect(({ routing }: ConnectState) => ({
id: routing.location.query.id,
}))(Comp);