前言
- 后台管理系统是电商系统不可或缺的部分。而富文本编辑器在电商后台里又是非常常见的一个功能。
- 自从前后端分离成为web项目主流,三大框架崛起,jquey成为过去式,jsp等项目逐渐被淘汰,一些优秀的“轮子”也停止了维护
- 旧的“轮子”已经停止了维护,却没有新的合适的“轮子”换上
我研究过的富文本编辑器: UEditor
,vue-quill-editor
,CKEditor
。区别:
-
UEditor
是百度的产品,是我用过最功能最全,最好用的一款。缺点却很致命:1、最新版本停留在了2016-05-26,没有后续更新了。2、最新版本任然有不少bug需要优化。3、前后端没有分离,在现在这个后端高傲到不理你的时代下,除非后端主动使用,否则基本无法完成对接。 -
vue-quill-editor
基于一款叫做quill
的vue版本,比UEditor
体积小了很多,同时功能也很大幅度的缩水,图片上传默认是转成base64插入到html代码中,严重影响上传的操作。 -
CKEditor
如果用过前两个,再来看这个,会给你一种眼前一亮的感觉,这是一个高度组件化的插件,几乎所有功能都拆分成组件需要引入。官方还提供了多种风格的编辑器,并且有集成版本和源码版本(集成版开箱即用,源码版自定义功能)。各个框架也有单独的适配组件,配合源码组合食用。
文章虽是自己手写,但学习借鉴了大佬的写过的一篇教程:https://blog.csdn.net/asing1elife/article/details/103936626
官网
CKEditor 5 - 官网
CKEditor 5 - 文档
CKEditor 5 - Github
编辑器风格
-
经典编辑器 Classic editor
-
内联编辑器 Inline editor
-
气球编辑器 Balloon editor
-
气球块编辑器 Balloon block editor
-
文件编辑器 Document editor
安装
这里以Classic editor版本结合vue框架使用为例
安装Classic editor编译版本@ckeditor/ckeditor5-build-classic
和用于对接vue框架的插件@ckeditor/ckeditor5-vue
npm install --save @ckeditor/ckeditor5-build-classic
npm install --save @ckeditor/ckeditor5-vue
// Or 同时安装
npm install --save @ckeditor/ckeditor5-build-classic @ckeditor/ckeditor5-vue
官方建议是全局调用ckeditor5-vue
,我们当然是没必要的,封装在单独的组件里就行了
接下来简单调用一下ckeditor插件,看一下效果如何:
<template>
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</template>
<script>
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import CKEditor from '@ckeditor/ckeditor5-vue'
export default {
name: 'CKEditor',
components: {
ckeditor: CKEditor.component
}
data () {
return {
// 编辑器组件传入编辑器实例
editor: ClassicEditor,
// 内容数据
editorData: '',
// 编辑器配置
editorConfig: {
// 内容为空时显示的提示文字
placeholder: this.placeholder,
}
}
}
}
</script>
<style lang="scss" scoped></style>
源码版本自定义集成
通常情况下,官方集成的默认版本,并不能完全符合自己的业务需求,这个时候就需要自定义源码集成版本了
官方文档提供了源码版本的使用教程
首先需要安装依赖
// 编辑器vue组件
npm install --save @ckeditor/ckeditor5-vue
// 编辑器的webpack插件
npm install --save-dev @ckeditor/ckeditor5-dev-webpack-plugin
npm install --save-dev @ckeditor/ckeditor5-dev-utils
// webpack使用的loader插件
npm install --save-dev postcss-loader@3
npm install --save-dev raw-loader@0.5.1
然后编辑webpack配置
官方以vue-cli 3.x
为例,也就是单独编辑vue.config.js
文件,如果使用的是vue-cli
更低的版本,将无法使用vue.config.js
文件配置,因此建议升级到vue-cli 3.x
以上的版本。
vue-cli
的升级,我没有去了解,但是笨办法还是可以有效解决的,新建一个vue项目,直接用vue-cli 3.x
以上的版本新建,然后把src整体复制一遍,package.json
复制一遍,有额外的webpack的配置,也复制到vue.config.js
中,还有项目的版本库别忘了.git
文件夹或.svn
文件夹,最后重新npm install
一遍
如果有特殊原因,不方便使用vue-cli 3.x
以上的版本,可以直接在2.x
版本中的webpack配置中做同样的配置,不过需要提前对webpack有所了解
下面是vue.config.js
中的配置,能看懂wabpack的小伙伴可以仔细看看配置了什么东西,看不懂的直接复制也ok
const path = require('path');
const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const {
styles
} = require('@ckeditor/ckeditor5-dev-utils');
module.exports = {
// The source of CKEditor is encapsulated in ES6 modules. By default, the code
// from the node_modules directory is not transpiled, so you must explicitly tell
// the CLI tools to transpile JavaScript files in all ckeditor5-* modules.
transpileDependencies: [
/ckeditor5-[^/\\]+[/\\]src[/\\].+\.js$/,
],
configureWebpack: {
plugins: [
// CKEditor needs its own plugin to be built using webpack.
new CKEditorWebpackPlugin({
// See https://ckeditor.com/docs/ckeditor5/latest/features/ui-language.html
language: 'zh-cn',
addMainLanguageTranslationsToAllAssets: true
})
]
},
// Vue CLI would normally use its own loader to load .svg and .css files, however:
// 1. The icons used by CKEditor must be loaded using raw-loader,
// 2. The CSS used by CKEditor must be transpiled using PostCSS to load properly.
chainWebpack: config => {
// (1.) To handle editor icons, get the default rule for *.svg files first:
const svgRule = config.module.rule('svg');
// Then you can either:
//
// * clear all loaders for existing 'svg' rule:
//
// svgRule.uses.clear();
//
// * or exclude ckeditor directory from node_modules:
svgRule.exclude.add(path.join(__dirname, 'node_modules', '@ckeditor'));
// Add an entry for *.svg files belonging to CKEditor. You can either:
//
// * modify the existing 'svg' rule:
//
// svgRule.use( 'raw-loader' ).loader( 'raw-loader' );
//
// * or add a new one:
config.module
.rule('cke-svg')
.test(/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/)
.use('raw-loader')
.loader('raw-loader');
// (2.) Transpile the .css files imported by the editor using PostCSS.
// Make sure only the CSS belonging to ckeditor5-* packages is processed this way.
config.module
.rule('cke-css')
.test(/ckeditor5-[^/\\]+[/\\].+\.css$/)
.use('postcss-loader')
.loader('postcss-loader')
.tap(() => {
return styles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('@ckeditor/ckeditor5-theme-lark'),
},
minify: true
});
});
}
};
其他依赖安装
上面安装了项目的配置依赖,接下来安装源码依赖
// npm install --save @ckeditor/ckeditor5-vue
npm install --save @ckeditor/ckeditor5-editor-classic
npm install --save @ckeditor/ckeditor5-essentials
npm install --save @ckeditor/ckeditor5-basic-styles
npm install --save @ckeditor/ckeditor5-link
npm install --save @ckeditor/ckeditor5-paragraph
npm install --save @ckeditor/ckeditor5-theme-lark
创建编辑器组件
自定义内容比较多,所以需要构建一个编辑器组件来封装功能
1、 先把上面安装步骤中的基础用法封装一下,封装成一个数据双向绑定的独立组件
<template>
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</template>
<script>
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import CKEditor from '@ckeditor/ckeditor5-vue'
export default {
name: "Editor",
components: {
ckeditor: CKEditor.component
},
props: {
value: {
type: String,
default: ""
}
},
data() {
return {
editor: ClassicEditor,
editorData: "",
editorConfig: {
// 内容为空时显示的提示文字
placeholder: this.placeholder,
}
};
},
watch: {
value(n) {
if (!this.editor) {
return;
}
// 外部内容发生变化时,将新值赋予编辑器
if (n && n !== this.editorData) {
this.editorData = this.value;
}
},
editorData(n) {
if (n && n !== this.value) {
// 编辑器内容发生变化时,告知外部,实现 v-model 双向监听效果
this.$emit("input", n);
}
}
},
created() {
this.editorData = this.value;
}
};
</script>
<style lang="scss" scoped></style>
2、 自定义集成,无非就是自己配置一个ClassicEditor实例去替代官方突出的默认的ClassicEditor@ckeditor/ckeditor5-build-classic
,这里稍微设计一些项目结构:因为是全局复用型的组件,我把它放在src/components
目录下,新建一个文件夹命名为Editor
也就是富文本组件。Editor
文件夹中新建index.vue
编辑器的主要文件,再新建一个core
文件夹存放ClassicEditor实例
index.vue
文件暂且先把上面封装好的编辑器组件复制过来
然后我们开始设计自定义的编辑器实例
3、 在core
文件夹中新建ckeditor.js
文件,引入基础包
import ClassicEditorBase from "@ckeditor/ckeditor5-editor-classic/src/classiceditor";
4、 根据实际需要引入功能插件
/* 逻辑功能 */
// 核心功能
import Essentials from "@ckeditor/ckeditor5-essentials/src/essentials";
// 格式相关
import Autoformat from "@ckeditor/ckeditor5-autoformat/src/autoformat";
// 段落
import Paragraph from "@ckeditor/ckeditor5-paragraph/src/paragraph";
// 粘贴功能
import PasteFromOffice from "@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice";
// 文本转换
import TextTransformation from "@ckeditor/ckeditor5-typing/src/texttransformation";
// 上传文件相关
import UploadAdapter from "@ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter";
import CKFinder from "@ckeditor/ckeditor5-ckfinder/src/ckfinder";
// 图片相关
import Image from "@ckeditor/ckeditor5-image/src/image";
import ImageCaption from "@ckeditor/ckeditor5-image/src/imagecaption";
import ImageStyle from "@ckeditor/ckeditor5-image/src/imagestyle";
import ImageToolbar from "@ckeditor/ckeditor5-image/src/imagetoolbar";
import ImageUpload from "@ckeditor/ckeditor5-image/src/imageupload";
/* 在编辑器顶部有按钮的功能 */
// 自定义服务器上传
import SimpleUploadAdapter from '@ckeditor/ckeditor5-upload/src/adapters/simpleuploadadapter';
// 缩进
import Indent from "@ckeditor/ckeditor5-indent/src/indent";
// 多媒体文件
import MediaEmbed from "@ckeditor/ckeditor5-media-embed/src/mediaembed";
// 标题
import Heading from "@ckeditor/ckeditor5-heading/src/heading";
// 字体颜色
import FontColor from "@ckeditor/ckeditor5-font/src/fontcolor";
// 字体背景颜色
import FontBackgroundColor from "@ckeditor/ckeditor5-font/src/fontbackgroundcolor";
// 字体大小
import FontSize from "@ckeditor/ckeditor5-font/src/fontsize";
// 字体种类
import FontFamily from "@ckeditor/ckeditor5-font/src/fontfamily";
// 粗体
import Bold from "@ckeditor/ckeditor5-basic-styles/src/bold";
// 斜体
import Italic from "@ckeditor/ckeditor5-basic-styles/src/italic";
// 下划线
import Underline from "@ckeditor/ckeditor5-basic-styles/src/underline";
// 中划线
import Strikethrough from "@ckeditor/ckeditor5-basic-styles/src/strikethrough";
// 上角标
import Subscript from "@ckeditor/ckeditor5-basic-styles/src/subscript";
// 下角标
import Superscript from "@ckeditor/ckeditor5-basic-styles/src/superscript";
// 超文本
import Link from "@ckeditor/ckeditor5-link/src/link";
// 列表
import List from "@ckeditor/ckeditor5-list/src/list";
// 引用文章
import BlockQuote from "@ckeditor/ckeditor5-block-quote/src/blockquote";
5、 创建ClassicEditor
类,继承ClassicEditor官方的基础类也就是ClassicEditorBase
,并export出去
export default class ClassicEditor extends ClassicEditorBase {}
6、 配置ClassicEditor
需要构建的插件
ClassicEditor.builtinPlugins = [
// 如果没有别的特殊设计,这里就是把上面引入的功能插件全部传进去
Essentials,
Autoformat,
UploadAdapter,
...
List,
BlockQuote
];
7、 配置初始参数
ClassicEditor.defaultConfig = {
// 编辑器菜单栏中的按钮项
toolbar: {
items: [
"heading",
"fontColor",
"fontBackgroundColor",
"fontsize",
"fontfamily",
"|",
"bold",
"italic",
"underline",
"strikethrough",
"subscript",
"superscript",
"|",
"link",
"blockQuote",
"|",
"bulletedList",
"numberedList",
// "|",
// "indent",
// "outdent",
"|",
"imageUpload",
"mediaEmbed",
"|",
"undo",
"redo"
]
},
// 图片的配置
image: {
toolbar: [
"imageStyle:full",
"imageStyle:side",
"|",
"imageTextAlternative"
]
},
// 这个language需要与webpack中配置的language保持一致
language: "zh-cn"
};
问题:使用源码版本,在npm run dev运行项目的时候会出现一个报错
[CKEditorWebpackPlugin] Error: No JS asset has been found during the compilation. You should add translation assets directly to the application from the `translations` directory. If that was intentional use the `buildAllTranslationsToSeparateFiles` option to get rif of the error.
[CKEditorWebpackPlugin] Error: No translation has been found for the zh-cn language.
研究了很久之后,在官方的github上看见了作者的答复,大致是说这是一直都存在的错误,历史版本里面把这个错误隐藏了,CKEditor5重新放出了这个错误,代码逻辑是正常的,报错不会有影响,以后会想办法解决这个错误
8、 完成组件封装
到这里,自定义的ClassicEditor
实列创建完成了,再回到刚才的src/component/Editor/index.vue
文件,把引入ClassicEditor
的那句改成引入自己的ClassicEditor
实例
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
// 改成
import ClassicEditor from "./core/ckeditor";
配置图片上传
未完待续。。。