CKeditor 編輯器使用記錄 (CKeditor 4 and 5 )
阿新 • • 發佈:2019-01-08
文章目錄
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"> <h2>Sample</h2> <p>This is an instance of the <a href="https://ckeditor.com/docs/ckeditor5/latest/builds/guides/overview.html#classic-editor">classic editor build</a>.</p> <figure class="image"><img src="../tests/manual/sample.jpg" alt="Autumn fields" /></figure> <p>You can use this sample to validate whether your <a href="https://ckeditor.com/docs/ckeditor5/latest/builds/guides/development/custom-builds.html">custom build</a> works fine.</p> </div> <script src="../build/ckeditor.js"></script> <script> ClassicEditor.create(document.querySelector("#editor"), { // config }) .then(editor => { window.editor = editor; }) .catch(err => { console.error(err.stack); }); </script>
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);
單檔案元件使用
<template> <div id="app"> <ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor> </div> </template> <script> import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; export default { name: 'app', data() { return { editor: ClassicEditor, editorData: '<p>Content of the editor.</p>', editorConfig: { // The configuration of the editor. } }; } } </script>
自定義圖片上傳
自定義圖片上傳外掛必需架構
// 自定義檔案上傳
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("<p>預設內容</p>");
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("<p>內容</p>");
獲取編輯器的內容,HTML
const editorContent = this.ckEditor.getData();
獲取編輯器的內容,純文字
this.ckEditor.getData().replace(/<[^>]*>/gi, "");
獲取編輯器的內容,過濾圖片
this.ckEditor.getData().replace(/<img.*?(?:>|\/>)/gi, "");
獲取編輯器的內容,過濾上傳的圖片
this.ckEditor.getData().replace(/<figure[^>]*.*?>.*?<\/figure>/gi, "");
獲取可用工具欄配置
Array.from(this.formControl.ckEditor.ui.componentFactory.names())
還原編輯器樣式
- 獲取編輯器內的DOM(未經轉換),在載入了編輯器 css 的專案中可還原
const _editorDom = this.ckEditor.editing.view.domRoots.get("main").outerHTML;
- 通過編輯器還原
與 CKEditor 4 不同,CKEditor 5 實現了自定義資料模型。這意味著載入到編輯器中的每個內容都需要轉換為該模型,然後再渲染回檢視。
每種內容都必須由某些功能處理。該功能定義了HTML(檢視)和編輯器模型之間的雙向轉換。
<div id="showContent"></div>
ClassicEditor.create(document.querySelector('#showContent')).then(editor => {
editor.isReadOnly = true; // 將編輯器設為只讀
editor.setData(editorContent) // 顯示內容 editorContent
}).catch(msg => {
console.error(msg);
});