CKeditor 编辑器使用记录 (CKeditor 4 and 5 )

文章目录

  • CKeditor 编辑器
    • CKeditor 4 使用
      • 自定义构建
    • CKeditor 5 使用
      • CDN 使用
      • npm 使用
      • 自定义图片上传
      • 自定义图片上传(七牛云)
      • 自定义构建
      • 基本操作
      • 还原编辑器样式

CKeditor 编辑器

CKeditor 是一款可定制的适合开发人员使用的富文本编辑器

编辑器官网

CKeditor 4 使用

官网

自定义构建

构建页面

常用插件

Code tag
Easy Image
Find / Replace
Font Size and Family
Letter-spacing
Line Height
Page Break
Paragraph Indentation
Statistics of the number of characters
Stored automatically in the browser storage
Text Transform

CKeditor 5 使用

CDN 使用

div id="editor">
	

Sample

This is an instance of the classic editor build.

Autumn fields

You can use this sample to validate whether your custom build works fine.

npm 使用

官方文档

安装

npm install --save @ckeditor/ckeditor5-vue @ckeditor/ckeditor5-build-classic

main.js引入

import Vue from 'vue';
import CKEditor from '@ckeditor/ckeditor5-vue';

Vue.use(CKEditor);

单文件组件使用




自定义图片上传

自定义图片上传插件必需架构

// 自定义文件上传
	class MyUploadAdapter {
		constructor(loader, url) {
			// 上传期间要使用的 FileLoader 实例。 
			this.loader = loader;

			// 服务器后端的上传URL。 这 是XMLHttpRequest 将图像数据发送到的地址。
			this.url = url;
		}

		// 上传
		upload() {
			return new Promise((resolve, reject) => {
			    // 自定义上传逻辑。。。 假设 response 为响应数据
			
			    // 上传失败时必须调用 reject() 函数
				if (!response || response.error) {
				   return reject(errorMessage);
				}
				
				// 如果上传成功,请调用 resolve() 并传入至少包含 {default: URL} 的对象,该 URL 为上传图像在服务器上的地址。
				resolve({
				   default: response.url // // 此 URL 将用于在内容中显示图像。 
				});
			});
		}

		// 中止上传
		abort() {
			if (this.xhr) {
				this.xhr.abort();
			}
		}
	}
	

自定义图片上传插件

    // 自定义文件上传
	class MyUploadAdapter {
		constructor(loader, url) {
			// 上传期间要使用的 FileLoader 实例。 
			this.loader = loader;

			// 服务器后端的上传URL。 这 是XMLHttpRequest 将图像数据发送到的地址。
			this.url = url;
		}

		// 开始上传
		upload() {
			return new Promise((resolve, reject) => {
				this._initRequest();
				this._initListeners(resolve, reject);
				this._sendRequest();
			});
		}

		// 中止上传
		abort() {
			if (this.xhr) {
				this.xhr.abort();
			}
		}

		// 使用传递给构造函数的 URL 初始化 XMLHttpRequest 对象。
		_initRequest() {
			const xhr = (this.xhr = new XMLHttpRequest());

			// 请注意,您的请求可能会有所不同。 由您和您的编辑器集成来选择正确的通信渠道。 此示例使用带有JSON的POST请求作为数据结构,但您的配置可能不同。
			xhr.open("POST", this.url, true);
			xhr.responseType = "json";
		}

		// 初始化 XMLHttpRequest 侦听器。
		_initListeners(resolve, reject) {
			const xhr = this.xhr;
			const loader = this.loader;
			const genericErrorText = "Couldn't upload file:" + ` ${loader.file.name}.`;

			xhr.addEventListener("error", () => reject(genericErrorText));
			xhr.addEventListener("abort", () => reject());
			xhr.addEventListener("load", () => {
				const response = xhr.response;

			    // 上传失败时必须调用 reject() 函数。
				if (!response || response.error) {
				   return reject(response && response.error ? response.error.message : genericErrorText);
				}

				// 如果上传成功,请使用至少包含 {default: URL} 的对象,该 URL 为上传图像在服务器上的地址。
				resolve({
				   default: response.url // // 此URL将用于在内容中显示图像。 
				});
			
			});

			// 支持上传进度。 FileLoader 具有 uploadTotal 和 uploaded 属性,如果使用它们,在编辑器的界面中将会显示上传的进度条。
			if (xhr.upload) {
				xhr.upload.addEventListener("progress", evt => {
					if (evt.lengthComputable) {
						loader.uploadTotal = evt.total;
						loader.uploaded = evt.loaded;
					}
				});
			}
		}
		// 准备数据并发送请求。
		_sendRequest() {
			// 准备表单数据。
			const data = new FormData();
			data.append("upload", this.loader.file);

			// 发送请求。
			this.xhr.send(data);
		}
	}

对接插件,以便在初始化编辑器时使用

	// 对接插件
	function MyCustomUploadAdapterPlugin(editor) {
		editor.plugins.get("FileRepository").createUploadAdapter = loader => {
			// Configure the URL to the upload script in your back-end here!
			return new MyUploadAdapter(loader, "https://img.sqydt.darongshutech.com/");
		};
	}

初始化编辑器,并加载自定义图片上传功能

	// 创建编辑器实例,并加载自定义图片上传功能
	ClassicEditor.create(document.querySelector("#editor"), {
		extraPlugins: [MyCustomUploadAdapterPlugin]
	})
	.then(editor => {
		window.editor = editor;
	})
	.catch(err => {
		console.error(err.stack);
	});

自定义图片上传(七牛云)

import axios from "axios";
window.axios = axios;
function MyCustomUploadAdapterPlugin(editor) {
  editor.plugins.get("FileRepository").createUploadAdapter = loader => {
    // Configure the URL to the upload script in your back-end here!
    return new MyUploadAdapter(loader, 10, "api/public/getUploadToken");
  };
}
// 自定义七妞云上传
class MyUploadAdapter {
  constructor(loader, maxSize, getToken) {
    // 上传期间要使用的 FileLoader 实例。
    this.loader = loader;

    // 图片大小限制
    this.maxSize = maxSize;

    // 获取上传七牛云token,接口地址
    this.upTokenUrl = getToken;

    // 允许上传的图片格式
    this.acceptString = ".jpg,.jpeg,.png,.gif,.JPG,.JPEG,.PNG,.GIF";

    // 七牛云上传地址
    this.qiniuUrl = "http://up.qiniu.com";

    // 文件存放地址
    this.baseUrl = "https://img.rmsq.com/";
  }

  // 上传
  upload() {
    return new Promise((resolve, reject) => {
      this._uploadFile(resolve, reject);
    });
  }

  // 中止上传
  abort() {
    if (this.xhr) {
      this.xhr.abort();
    }
  }
  
  _uploadFile(resolveCK, rejectCK) {
    const file = this.loader.file;
    const isLt = file.size / 1024 / 1024 < this.maxSize;

    // const fileExt = _file.type.split("/")[1]; // .mp3 在火狐和ie 读取的格式为 mpeg
    const lastIndex = file.name.lastIndexOf(".");
    const fileExt = file.name.substring(+lastIndex + 1); // 上传的文件的格式
    const allAcceptArr = this.acceptString.split(","); // 允许上传的格式

    if (!this._isInArr("." + fileExt, allAcceptArr)) {
      console.error("请上传格式为" + this.acceptString + "的文件!");
      return false;
    }

    if (this.maxSize && !isLt) {
      console.error("请上传小于" + this.maxSize + "MB的文件!");
      return false;
    }

    // 使用FormData对象上传文件
    var formData = new FormData();
    formData.append("file", file);

    // 获取七牛云TOKEN
    this._getQiniuToken(fileExt).then(resData => {
      formData.append("token", resData.data.token);
      formData.append("key", resData.data.key);

      // 上传文件至七牛云
      this._requestQiniu(formData)
        .then(response => {
          // 如果上传成功,请调用 resolve() 并传入至少包含 {default: URL} 的对象,该 URL 为上传图像在服务器上的地址。
          resolveCK({
            default: this.baseUrl + response.key // // 此 URL 将用于在内容中显示图像。
          });
        })
        .catch(err => {
          // 上传失败
          rejectCK(err);
        });
    });
  }

  _isInArr(_val, _arr) {
    return _arr.some(item => {
      if (item === _val) {
        return true;
      }
    });
  }

  _getQiniuToken(fileExt) {
    return new Promise((resolve, reject) => {
      axios.get(this.upTokenUrl, { params: { file_ext: fileExt } }).then(res => {
        if (res && res.data && res.data.code === 2000) {
          resolve(res.data);
        } else {
          console.error(res.data.msg);
        }
      });
    });
  }

  _requestQiniu(formData) {
    const config = {
      headers: { "Content-Type": "multipart/form-data" },
      onUploadProgress: progressEvent => {
        // 上传进度
        this.loader.uploadTotal = progressEvent.total;
        this.loader.uploaded = progressEvent.loaded;
      }
    };
    return new Promise((resolve, reject) => {
      axios.post(this.qiniuUrl, formData, config).then(res => {
        if (res && res.status == 200) {
          resolve(res.data);
        } else {
          console.error(res.data.msg);
        }
      });
    });
  }
}

使用

    initEditor() {
      ClassicEditor.create(document.querySelector("#sqbCkEditor"), {
        // The configuration of the editor.
        language: "zh-cn",
        toolbar: ["undo", "redo", "|", "heading", "|", "fontSize", "bold", "italic", "link", "bulletedList", "numberedList", "blockQuote", "imageUpload", "imageStyle:full", "imageStyle:side"],
        extraPlugins: [MyCustomUploadAdapterPlugin] // 使用自定义上传图片插件
        // ckfinder: {
        //   uploadUrl: "http://up.qiniu.com"
        // }
      })
        .then(editor => {
          editor.setData("

默认内容

"); this.ckEditor = editor; }) .catch(msg => { console.log("msg", msg); }); },

自定义构建

文档描述

基本操作

汉化

  import "@ckeditor/ckeditor5-build-classic/build/translations/zh-cn.js";

  ClassicEditor.create(document.querySelector("#sqbCkEditor"), {
    // The configuration of the editor.
    language: "zh-cn",
    // ckfinder: {
    //   uploadUrl: "http://up.qiniu.com"
    // }
  })
    .then(editor => {
      console.log("asd", editor);
    })
    .catch(msg => {
      console.log("msg", msg);
    });

设置内容

this.ckEditor.setData("

内容

");

获取编辑器的内容,HTML

const editorContent = this.ckEditor.getData();

获取编辑器的内容,纯文本

this.ckEditor.getData().replace(/<[^>]*>/gi, "");

获取编辑器的内容,过滤图片

this.ckEditor.getData().replace(/|\/>)/gi, "");

获取编辑器的内容,过滤上传的图片

this.ckEditor.getData().replace(/]*.*?>.*?<\/figure>/gi, "");

获取可用工具栏配置

Array.from(this.formControl.ckEditor.ui.componentFactory.names())

还原编辑器样式

  1. 获取编辑器内的DOM(未经转换),在加载了编辑器 css 的项目中可还原
const _editorDom = this.ckEditor.editing.view.domRoots.get("main").outerHTML;
  1. 通过编辑器还原

与 CKEditor 4 不同,CKEditor 5 实现了自定义数据模型。这意味着加载到编辑器中的每个内容都需要转换为该模型,然后再渲染回视图。
每种内容都必须由某些功能处理。该功能定义了HTML(视图)和编辑器模型之间的双向转换。

    
ClassicEditor.create(document.querySelector('#showContent')).then(editor => { editor.isReadOnly = true; // 将编辑器设为只读 editor.setData(editorContent) // 显示内容 editorContent }).catch(msg => { console.error(msg); });

你可能感兴趣的:(vue,前端)