CKEditor5之初体验

7,001 阅读5分钟

1. 目标:实现一款包含以下功能的富文本编辑器

撤销、重做、加粗、下划线、斜体、左对齐、居中、右对齐、清空样式、插入图片

目标效果图如下:
目标编辑器模样

CKEditor官网示例里,在左边导航栏Builds里,点击切换,可以看到有几款富文本编辑器类型。下面以下以classic经典款为例。

2. 快速上手

选中左边菜单里的Classic editor, 可以看到经典款的默认UI展示,如下图所示:
classic编辑器模样

里面的工具栏里的工具和展示顺序是经典款默认的。

按照官方文档的操作:

  • 安装依赖包
npm install --save @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic
  • 在项目中使用
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

const MyEditor = () => {
  return (
    <CKEditor
      editor={ClassicEditor}
      data="<p>Hello from CKEditor 5!</p>"
      onReady={editor => {
        console.log('Editor is ready to use!', editor);
      }}
    />
  );
}

export default MyEditor;

项目运行,默认编辑器展示完好。如果你要的工具项都包含在默认编辑器里,那恭喜你,你只需要给CKEditor组件添加配置,配置里写好你要的工具名和顺序即可:

    <CKEditor
      editor={ClassicEditor}
      data="<p>Hello from CKEditor 5!</p>"
      config={{
        toolbar: ['undo', 'redo', '|', 'bold']
      }}
    />

3. 如何达到目标效果

其实CKEditor有很多可支持的现成插件,在默认的经典款编辑器里,其实就是默认封装使用了一堆的插件,比如Bold、Italic等等,默认还封装了哪些插件呢?我们可以这么查看:

CKEditor支持在线根据自己的需求构建代码,点击官网头部导航栏的online builder,第一步选择Classic类型,我们会来到第二步选择编辑器插件。默认Picked plugins里面的插件就是经典款封装的插件啦~~
在这里我们还可以添加我们需要的插件和删除我们用不到的插件。

再回到我们的目标,我们可以发现,我们需要的工具 下划线(Underline)、左对齐、居中、右对齐(Alignment)、清空样式(Remove format)不在默认的编辑器里。要达到我们的目标,我们有两种方法:

  • 方法一: 使用online builder在线自定义编译打包

打开online builder

  1. Choose editor type: 选择Classic类型;
  2. Choose editor plugins: 添加Underline、Alignment、Remove format三个插件,删除我们用不上的插件;
  3. Choose toolbar items:调整工具栏的工具显示顺序,点击删除不需要的工具;
  4. Choose the default editor language:选择编辑器的默认语言(在translations目录里可以找到其他的语言文件),我们勾选Chinese;
  5. 点击start构建我们自定义的编辑器,构建完成后下载;

解压我们下载下来的文件,我们可以得到这么一个文件夹:

文件夹图片

浏览器打开sample/index.html即可以看到我们自定义配置的编辑器效果了~ 接下来我们把我们自定义编译打包好的组件移到我们自己的项目:

  1. 在项目中新建添加组件文件夹,比如命名为CKEditor;
  2. 把上面图中build/ckeditor.js的文件内容拷贝到CKEditor/index.js;
  3. 复制需要的翻译。刚刚上面我们勾选的是Chinese,所以我们需要把build/translations/zh-cn.js复制到CKEditor/translations/zh-cn.js。

在项目中使用:

import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@/components/CKEditor';

const MyEditor = () => {
  return (
    <CKEditor
      editor={ClassicEditor}
      data="<p>Hello from CKEditor 5!</p>"
      config={{
        language: 'zh-cn',
        toolbar: [
          'undo',
          'redo',
          '|',
          'bold',
          'underline',
          'italic',
          'alignment',
          'removeFormat',
          '|',
          'imageUpload',
        ]
      }}
    />
  );
}

export default MyEditor;

运行可以看到我们需要的效果了:)

  • 方法二: 本地自定义编译打包

步骤:

  1. 克隆源码
git clone -b stable https://github.com/ckeditor/ckeditor5
  1. 先安装源码已有依赖
cd ckeditor5/packages/ckeditor5-build-classic
npm install
  1. 安装需要添加的依赖 根据我们的目标,我们需要添加插件Alignment和Remove format,依次安装。Underlinede包含在已安装的@ckeditor/ckeditor5-basic-styles中。
npm install --save-dev @ckeditor/ckeditor5-alignment
npm install --save-dev @ckeditor/ckeditor5-remove-format
  1. 编辑src/ckeditor.js ClassicEditor.builtinPlugins配置需要用到的插件
    ClassicEditor.defaultConfig默认配置
ClassicEditor.defaultConfig = {
  toolbar: {
    items: [
      'undo',
      'redo',
      '|',
      'bold',
      'underline',
      'italic',
      'numberedList',
      'bulletedList',
      'outdent',
      'indent',
      'alignment',
      'removeFormat',
      '|',
      'imageUpload',
    ]
  },
  image: {
    toolbar: [
      'imageStyle:full',
      'imageStyle:side',
      '|',
      'imageTextAlternative',
    ]
  },
  language: 'zh-cn'
};

配置时可以参考可以查看文档,插件的引用配完后应该和上面线上编译下载下来的src/ckeditor.js一致。

  1. 本地构建
npm run build

构建后会重新生成 build/ckeditor.js,到这一步,本地编译打包完成。

  1. 在项目中使用
  • 项目使用上可以用方法一一样使用,直接把生成好的当成下载下来的源码。
  • 如果有私库,也可以上传到私库,然后项目中去安装使用,同上文第2张图经典款直接使用。

但要注意一点,自定义打包,可以把想要的配置直接写到ClassicEditor.defaultConfig默认配置里,所以在使用时,如果和默认配置一致,可以不用重复配置了。

到这里,我们已经实现了目标UI的效果了,试用了下,工具栏上的功能都能work,但是上传照片却没有用,革命尚未成功呀!

4. 实现图片上传

这里我做了一个自定义的上传适配器:

class MyUploadAdapter {
  constructor(loader) {
    this.loader = loader;
  }
  upload() {
    return this.loader.file.then(file => new Promise((resolve, reject) => {
      const data = new FormData();
      const config = {
        headers: { 'content-type': 'multipart/form-data' }
      };
      data.append('file', file);
      axios.post(`${file_prefix}/uploadimage`, data, config).then(res => {
        if (res.data && res.data.status === 0) {
          resolve({
            default: res.data.data.key
          });
        } else {
          reject(res.data && res.data.message);
        }
      }).catch(err => {
        reject(err);
      });
    })
    )
  }

  abort() {
  }
}

然后把适配器运用到我们的编辑器中:

const MyCustomUploadAdapterPlugin = (editor) => {
  editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
    return new MyUploadAdapter(loader);
  };
};

// 在配置里添加插件

extraPlugins: [ MyCustomUploadAdapterPlugin ]

到这里我们的目标就达成啦~~