介绍
CKEditor5官网提供直接下载的富文本编辑器有以下五种,但无论是哪一种,其内部只配备了基础的插件,像“字体”,“对齐方式”这些功能,都属于需要额外配置的插件。本文主要介绍基于classic版本,自定义富文本编辑器,并完善图片上传功能
官网地址:https://ckeditor.com/ckeditor-5/
官网react安装地址:https://ckeditor.com/docs/ckeditor5/latest/installation/integrations/react.html
github地址:https://github.com/ckeditor/ckeditor5
自定义编辑器
- 如果需要自定义ckeditor5,需要基于ckeditor5的源码,自己再添加插件。所以首先需要从 github 下载ckeditor5源码,推荐使用stable分支。下载完后进入package下的ckeditor5-build-classic文件夹,执行
npm i
命令,classic是基础版本,我们只需要基于该版本修改就好
- 执行完毕后,再执行
npm run build
命令,生成build文件。这时候访问sample下的index.html
文件,可以预览打包后的效果 - 这里我需要给编辑器添加“对齐方式”和“字体”的插件,执行
npm install @ckeditor/ckeditor5-alignment @ckeditor/ckeditor5-font
安装插件。点击 官网插件列表 查看可以安装的所有功能,官网插件安装教程 也提供了安装过程 - 安装完毕后打开src下的
ckeditor.ts
文件,在其中添加所需要的插件。代码如下,已修改的地方我用注释标注了
import { ClassicEditor as ClassicEditorBase } from '@ckeditor/ckeditor5-editor-classic';
import { Essentials } from '@ckeditor/ckeditor5-essentials';
import { UploadAdapter } from '@ckeditor/ckeditor5-adapter-ckfinder';
import { Autoformat } from '@ckeditor/ckeditor5-autoformat';
import { Bold, Italic } from '@ckeditor/ckeditor5-basic-styles';
import { BlockQuote } from '@ckeditor/ckeditor5-block-quote';
import { CKBox } from '@ckeditor/ckeditor5-ckbox';
import { CKFinder } from '@ckeditor/ckeditor5-ckfinder';
import { EasyImage } from '@ckeditor/ckeditor5-easy-image';
import { Heading } from '@ckeditor/ckeditor5-heading';
// classic中所使用的image一开始未引入ImageResize,图片不能调整大小,所以这里我额外又引入了ImageResize
import { Image, ImageCaption, ImageStyle, ImageToolbar, ImageUpload, PictureEditing, ImageResize } from '@ckeditor/ckeditor5-image';
import { Indent } from '@ckeditor/ckeditor5-indent';
import { Link } from '@ckeditor/ckeditor5-link';
import { List } from '@ckeditor/ckeditor5-list';
import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office';
import { Table, TableToolbar } from '@ckeditor/ckeditor5-table';
import { TextTransformation } from '@ckeditor/ckeditor5-typing';
import { CloudServices } from '@ckeditor/ckeditor5-cloud-services';
// 引入alignment和font
import { Alignment } from '@ckeditor/ckeditor5-alignment';
import { Font } from '@ckeditor/ckeditor5-font';
export default class ClassicEditor extends ClassicEditorBase {
public static override builtinPlugins = [
Essentials,
UploadAdapter,
Autoformat,
Bold,
Italic,
BlockQuote,
CKBox,
CKFinder,
CloudServices,
EasyImage,
Heading,
Image,
ImageCaption,
ImageStyle,
ImageToolbar,
ImageUpload,
// 添加ImageResize
ImageResize,
Indent,
Link,
List,
MediaEmbed,
Paragraph,
PasteFromOffice,
PictureEditing,
Table,
TableToolbar,
TextTransformation,
// 添加这两个插件
Alignment,
Font
];
public static override defaultConfig = {
toolbar: {
// 在toolbar中配置展示对齐方式和字体的展示位置
// font包含了字体,文字大小,文字颜色,文字背景色等功能,每一项需要单独引入,我这里添加了'fontSize', 'fontColor'这两项
items: [
'undo', 'redo',
'|', 'heading', 'alignment',
'|', 'fontSize', 'fontColor', 'bold', 'italic',
'|', 'link', 'uploadImage', 'insertTable', 'blockQuote', 'mediaEmbed',
'|', 'bulletedList', 'numberedList', 'outdent', 'indent'
]
},
image: {
toolbar: [
'imageStyle:inline',
'imageStyle:block',
'imageStyle:side',
'|',
'toggleImageCaption',
'imageTextAlternative'
]
},
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells'
]
},
// This value must be kept in sync with the language defined in webpack.config.js.
language: 'en'
};
}
- 再次执行
npm run build
,打开index.html
查看运行效果。可以看到对齐和字体都已经被打包成功,可以正确展示
项目使用自定义编辑器
- 项目使用自定义编辑器有几种方式,我这里偷懒直接使用了第三种方式
1.打包发布至npm,再引入
2.使用build文件替换node_modules中classic的文件
3.将打包后build文件中的ckeditor.js文件直接引入 - 打开自己的react项目目录,执行
npm i @ckeditor/ckeditor5-react
- 安装完毕后,打开需要使用富文本编辑器的文件。
引入的ckeditor是我放在当前目录下的ckeditor.js,随便放在哪里都行,但是不要忘记引入
import {CKEditor} from '@ckeditor/ckeditor5-react'
import './ckeditor'
const handleEditor = (newContent) => {
this.setState({ content: newContent })
}
// 在需要使用CKEditor的位置使用该组件
<CKEditor
editor={ClassicEditor}
placeholder='请编辑详情'
data={this.state.content}
onBlur={ ( event, editor ) => {
const data = editor.getData();
this.handleEditor(data)
} }
/>
- 再次运行项目,就可以看到CKEditor已经展示了对齐等效果
完善图片上传功能
- 在同目录下添加
CKImageUpload.js
,代码如下。代码基于 官网自定义上传图片功能 修改
class MyUploadAdapter {
constructor( loader ) {
this.loader = loader;
}
upload() {
return this.loader.file
.then( file => new Promise( ( resolve, reject ) => {
this._initRequest();
this._initListeners( resolve, reject, file );
this._sendRequest( file );
} ) );
}
abort() {
if ( this.xhr ) {
this.xhr.abort();
}
}
_initRequest() {
const xhr = this.xhr = new XMLHttpRequest();
// 修改为自己项目的接口地址
xhr.open( 'POST', '/api/files/uploadFile', true );
xhr.responseType = 'json';
}
_initListeners( resolve, reject, file ) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = `图片${ file.name }上传失败`;
xhr.addEventListener( 'error', () => reject( genericErrorText ) );
xhr.addEventListener( 'abort', () => reject() );
xhr.addEventListener( 'load', () => {
// 这里限制了一下图片上传大小
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
return reject( `图片${ file.name }大小超出2M,请重新上传` );
}
const response = xhr.response;
if ( !response || response.error ) {
return reject( response && response.error ? response.error.message : genericErrorText );
}
resolve( {
// 这里要根据后端接口取图片地址
default: response.url
} );
} );
if ( xhr.upload ) {
xhr.upload.addEventListener( 'progress', evt => {
if ( evt.lengthComputable ) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
} );
}
}
_sendRequest( file ) {
const data = new FormData();
// 'file'要根据自己的接口字段填写
data.append( 'file', file );
this.xhr.send( data );
}
}
export const UploadAdapterPlugin = ( editor ) => {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
return new MyUploadAdapter( loader );
};
}
- 再次打开使用了编辑器的文件,引入图片上传功能,修改CKEditor组件,添加
config
配置
import {CKEditor} from '@ckeditor/ckeditor5-react'
import './ckeditor'
import {UploadAdapterPlugin} from './CKImageUpload'
<CKEditor
config={{
extraPlugins: [ UploadAdapterPlugin ]
}}
editor={ClassicEditor}
placeholder='请编辑详情'
data={this.state.content}
onBlur={ ( event, editor ) => {
const data = editor.getData();
this.handleEditor(data)
} }
/>
- 重新运行项目,图片上传功能可以使用了