React使用自定义CKEditor5,并完善图片上传功能

介绍

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已经展示了对齐等效果

完善图片上传功能

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)
    } }
/>
  • 重新运行项目,图片上传功能可以使用了
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值