CKEditor接入阿里云oss上傳圖片

csdn本文鏈接:https://blog.csdn.net/u010004317/article/details/89513099

一. 前言

目前公司使用的富文本編輯器是百度的UEditor,目前其最新的版本停留在了16年的版本,基本算是無(wú)人維護(hù)的了,作為一個(gè)傳統(tǒng)但是強(qiáng)勁的富文本編輯器,UEditor在初期的確是很多學(xué)生或者小型創(chuàng)業(yè)公司后臺(tái)開(kāi)發(fā)的首選富文本編輯器,但是隨著業(yè)務(wù)的深入,UEditor的問(wèn)題也暴露出來(lái)了。

  • 代碼結(jié)構(gòu)復(fù)雜,無(wú)法很好地自定義和擴(kuò)展(這個(gè)是很重要的原因,改起來(lái)真的很麻煩)

  • bug多,不夠穩(wěn)定

  • 樣式太過(guò)老舊

富文本編輯器對(duì)于我們來(lái)說(shuō),要簡(jiǎn)單,夠用就好了,太多花里胡哨的功能我們都不需要用到,參考過(guò)公眾號(hào)和知乎的富文本編輯器,都是很簡(jiǎn)單的,雖然對(duì)對(duì)于我們做電商來(lái)說(shuō)太過(guò)簡(jiǎn)單了,但是基本功能和樣式就是我們想要的,我們完全可以在其基礎(chǔ)上進(jìn)行擴(kuò)展。

另外個(gè)原因,我們的圖片服務(wù)器是oss,所以需要通過(guò)富文本編輯器直傳圖片到oss中,直接在百度UEditor中,花了很大的力氣接入了oss,雖然功能基本實(shí)現(xiàn)了,但是效果很不理想,無(wú)法所見(jiàn)即所得。

基于以上種種,我在市面上找了好幾個(gè)編輯器,但是效果都不是很理想,接下來(lái)我列一下。

1. Editor.js

  • 官網(wǎng):https://editorjs.io/

  • 簡(jiǎn)介:該編輯器是以塊作為基本元素來(lái)的,每次編輯都是在一個(gè)塊上進(jìn)行編輯,主要的特點(diǎn)是,它的輸出是json格式的,而不是傳統(tǒng)的html格式,這是我非常喜歡的??勺远x插件,操作簡(jiǎn)單快捷。

  • 建議:該編輯器適合業(yè)務(wù)不復(fù)雜的場(chǎng)景,以及只有pc端展示的場(chǎng)景,如寫(xiě)簡(jiǎn)單文章之類的,如果對(duì)于公司來(lái)說(shuō),需要從word編輯,需要提供移動(dòng)端做html展示(對(duì)于ios和安卓來(lái)說(shuō),他們只能通過(guò)html來(lái)做渲染,無(wú)法引入該編輯器),該編輯器則無(wú)法實(shí)現(xiàn)

在這里插入圖片描述

2. NKeditor

  • 官網(wǎng):https://gitee.com/blackfox/kindeditor

  • 簡(jiǎn)介:基于 kindeditor 進(jìn)行二次開(kāi)發(fā)的項(xiàng)目,文檔少,理解困難,這是產(chǎn)品找給我的

  • 建議:不推薦用,沒(méi)文檔的開(kāi)源就是坑,而且還是二次開(kāi)發(fā)的。

在這里插入圖片描述

3. wangEditor

  • 官網(wǎng):http://www.wangeditor.com/

  • 簡(jiǎn)介:這款是我在網(wǎng)上發(fā)現(xiàn)很多人推崇的,github的star數(shù)也有7000多,算是比較活躍的一款開(kāi)源編輯器,文檔算是比較齊全,我剛開(kāi)始也是覺(jué)得挺OK的,但是另外一個(gè)方面我覺(jué)得他的自定義插件功能不夠強(qiáng)大,我的項(xiàng)目對(duì)自定義插件的要求很高,所以放棄

  • 建議:對(duì)自定義插件功能要求不高的,我推薦這款編輯器

在這里插入圖片描述

4. CKEditor

https://ckeditor.com/ (CKEditor地址)

  • 簡(jiǎn)介:CKEditor分CKEditor4和CKEditor5,因?yàn)镃KEditor5要用到npm打包,并且其缺少了一些我覺(jué)得很重要的功能,所以我選擇了CKEditor4,而且CKEditor5比較新,CKEditor4經(jīng)歷過(guò)了一段時(shí)間的考驗(yàn)。這也是在機(jī)緣巧合之下發(fā)現(xiàn)了這款編輯器,是國(guó)外開(kāi)源的一款編輯器,擁有自己的詳細(xì)的官網(wǎng),而且官網(wǎng)做得還不錯(cuò),github的社區(qū)也十分活躍,最近一次提交也是在一個(gè)月內(nèi),讓我看到了他的可靠性,至少在未來(lái)兩年內(nèi),該框架都會(huì)持續(xù)更新和優(yōu)化,從長(zhǎng)遠(yuǎn)來(lái)看,這都是其他編輯其所無(wú)法實(shí)現(xiàn)的。

  • 他提供了多種編輯器樣式供選擇,而且文檔很詳細(xì),老外寫(xiě)的文檔,不得不說(shuō),真的很詳細(xì),雖然很長(zhǎng),像nginx,spring-boot的文檔一樣。而且文檔中有各種demo,并且demo也提供了源碼,給初學(xué)者提供了一個(gè)很好的入門(mén)機(jī)會(huì)。

  • 建議:強(qiáng)烈推薦,只是是英文文檔,讀起來(lái)有點(diǎn)費(fèi)力,不過(guò)技術(shù)英文文檔估計(jì)是最簡(jiǎn)單的英文入門(mén)了,所用詞匯相對(duì)簡(jiǎn)單,再結(jié)合詞典就很容易理解了,不推薦把整個(gè)文檔翻譯成中文來(lái)看,先讀英文文檔,發(fā)現(xiàn)不懂的單詞再去查詞典,結(jié)合上下文理解他的語(yǔ)境。

在這里插入圖片描述
在這里插入圖片描述

二. 搭建基礎(chǔ)的CKEditor框架

1. 基本配置

官網(wǎng)下載文件,下載界面可選:Basic Package、Standard Package、Full Package、Customize。根據(jù)自己需求下載不同的安裝包,而且每種都有壓縮版和源碼版可選。其中Customize版本顧名思義可自定義選擇自己需要的模塊,官方也推薦使用這種方式自定義下載。Customize版本相當(dāng)于在線上讓你通過(guò)圖形化界面自定義自己想要的插件和皮膚樣式等,說(shuō)實(shí)在,這個(gè)功能很強(qiáng)大。

1. 1 引入js

<script src="../install package/ckeditor/ckeditor.js"></script>

1.2 寫(xiě)一個(gè)textarea標(biāo)簽

  <textarea name="editor1" id="editor1" rows="10" cols="80">

        This is my textarea to be replaced with CKEditor.

    </textarea>

1.3 初始化CKEditor

CKEDITOR.replace('editor1', {

    uiColor: '#9AB8F3'

});

1.4 完整代碼

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <script src="../../install package/ckeditor/ckeditor.js"></script>

    <link href="simple-image.css" rel="stylesheet" />

</head>

<form action="" method="post" onclick="save()">

    <textarea name="editor1" id="editor1" rows="10" cols="80">

        This is my textarea to be replaced with CKEditor.

    </textarea>



</form>

<script>



        window.onload = function() {



        }

        // Replace the <textarea id="editor1"> with a CKEditor

        // instance, using default configuration.

        CKEDITOR.replace('editor1', {

            uiColor: '#9AB8F3'

        });

        function save() {

            var data = CKEDITOR.instances.editor1.getData();

            alert(data)

            console.log(data);

        }

    </script>

<body>

</body>

</html>

1.5 效果
在這里插入圖片描述

2. 自定義配置

CKEditor做得十分人性化,它不需要你去讀文檔,知道每個(gè)插件圖標(biāo)的的配置信息,然后去代碼中手動(dòng)添加或移除,他在full的文檔中提供了一個(gè)html頁(yè)面,可以通過(guò)圖形化界面自定義配置信息,該html的頁(yè)面在ckeditor?/sample/index.html

在這里插入圖片描述
在這里插入圖片描述

生成的配置文件

在這里插入圖片描述

代碼配置


CKEDITOR.replace('editor1', {

          toolbarGroups: [

                { name: 'document', groups: [ 'mode', 'document', 'doctools' ] },

                { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },

                { name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },

                { name: 'forms', groups: [ 'forms' ] },

                '/',

                { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },

                { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },

                { name: 'links', groups: [ 'links' ] },

                { name: 'insert', groups: [ 'insert' ] },

                '/',

                { name: 'styles', groups: [ 'styles' ] },

                { name: 'colors', groups: [ 'colors' ] },

                { name: 'tools', groups: [ 'tools' ] },

                { name: 'others', groups: [ 'others' ] },

                { name: 'about', groups: [ 'about' ] }

            ],

            removeButtons:  'Source,Save,Templates,Undo,Find,SelectAll,Scayt,Form,Bold,CopyFormatting,NumberedList,Outdent,Blockquote,JustifyLeft,BidiLtr,Link,Image,Cut,Copy,Redo,Replace,NewPage,Preview,Print,Paste,PasteText,PasteFromWord,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField',

            allowedContent: false  //關(guān)閉acf功能,不建議關(guān)閉

      });

三. CKEditor自定義插件

CKEditor4提供了強(qiáng)大的自定義插件功能,強(qiáng)烈建議根據(jù)它的官方文檔中的4個(gè)demo一個(gè)個(gè)手敲一遍,而且一個(gè)都不要落下,敲完之后你會(huì)對(duì)CKEditor4的自定義插件有個(gè)更加深入的認(rèn)識(shí)。因?yàn)楣居玫降膱D片服務(wù)器是阿里云的oss,所以需要在編輯器中接入oss,針對(duì)圖片都上傳到oss中,我這邊就簡(jiǎn)單介紹下如何自定義oss上傳插件

1. 文件結(jié)構(gòu)

CKEditor4規(guī)定自定義插件,必須要在plugins目錄下新建一個(gè)插件同名文件夾,然后在該文件夾下有plugin.js(用于寫(xiě)插件的初始化等基本信息),dailog文件夾,該文件夾下的js用于實(shí)現(xiàn)對(duì)話框的具體業(yè)務(wù)邏輯,icons文件夾,該文件夾下有xxx.png的圖片,作為插件的圖標(biāo)。


uploadimages

......dialog

.............uploadimage.js

.............upload.js

......icons

.............uploadimages.png

......plugin.js

2. 代碼

2.1 plugin.js

CKEDITOR.plugins.add('uploadimages', {

icons: 'uploadimages',

//初始化方法

init: function(editor) {

//添加命令,最簡(jiǎn)單的自定義插件,可以在addCommand這個(gè)方法里面,通過(guò)定義exec,直接插入相應(yīng)的html即可

/***** 

演示最簡(jiǎn)答的自定義插件,插入相應(yīng)的html,與本例子無(wú)關(guān)

editor.addCommand('insertTimestamp', {

exec: function(editor) {

var now = new Date();

editor.insertHtml('<p>The current date and time is232323232: ' + now.toString() + 'xcxzc</p><br/>');

}

});

****/

editor.addCommand('uploadimages', new CKEDITOR.dialogCommand('uploadimagesDialog', {

// allowedContent: 'abbr[title,id]',

// requiredContent: 'abbr'

}));

//添加插件按鈕

editor.ui.addButton('UploadImages', {

label: '上傳圖片',

command: 'uploadimages',

toolbar: 'insert'

});

//添加對(duì)話框,配置實(shí)現(xiàn)對(duì)話框邏輯的js文件

CKEDITOR.dialog.add('uploadimagesDialog', this.path + 'dialog/uploadimages.js');

}

});

2.2. upload.js

我們使用的oss上傳是通過(guò)官方提供的plupload.Uploader與后臺(tái)進(jìn)行交互獲取秘鑰等信息進(jìn)行上傳的,在CKEditor,官方提供的例子要做些修改

由下面的代碼可以看出,官方提供的例子的plupload.Uploader的初始化方法被我移走了,是的,初始化事件要在CKEditor中完成,


accessid = ''

accesskey = ''

host = ''

policyBase64 = ''

signature = ''

callbackbody = ''

filename = ''

key = ''

expire = 0

g_object_name = ''

g_object_name_type = 'local_name'

now = timestamp = Date.parse(new Date()) / 1000;

function send_request()

{

    var xmlhttp = null;

    if (window.XMLHttpRequest)

    {

        xmlhttp=new XMLHttpRequest();

    }

    else if (window.ActiveXObject)

    {

        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

    }



    if (xmlhttp!=null)

    {

        // serverUrl是 用戶獲取 '簽名和Policy' 等信息的應(yīng)用服務(wù)器的URL,請(qǐng)將下面的IP和Port配置為您自己的真實(shí)信息。

        serverUrl = 'http://xxxxxxxx/api/oss/getOssServer'

        xmlhttp.open( "GET", serverUrl, false );

        xmlhttp.send( null );

        return xmlhttp.responseText

    }

    else

    {

        alert("Your browser does not support XMLHTTP.");

    }

};

function check_object_radio() {

    var tt = document.getElementsByName('myradio');

    for (var i = 0; i < tt.length ; i++ )

    {

        if(tt[i].checked)

        {

            g_object_name_type = tt[i].value;

            break;

        }

    }

}

function get_signature()

{

    // 可以判斷當(dāng)前expire是否超過(guò)了當(dāng)前時(shí)間, 如果超過(guò)了當(dāng)前時(shí)間, 就重新取一下,3s 作為緩沖。

    now = timestamp = Date.parse(new Date()) / 1000;

    if (expire < now + 3)

    {

        body = send_request()

        var obj = eval ("(" + body + ")");

        host = obj['host']

        policyBase64 = obj['policy']

        accessid = obj['accessid']

        signature = obj['signature']

        expire = parseInt(obj['expire'])

        callbackbody = obj['callback']

        key = obj['dir']

        return true;

    }

    return false;

};

function random_string(len) {

  len = len || 32;

  var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; 

  var maxPos = chars.length;

  var pwd = '';

  for (i = 0; i < len; i++) {

      pwd += chars.charAt(Math.floor(Math.random() * maxPos));

    }

    return pwd;

}

function get_suffix(filename) {

    pos = filename.lastIndexOf('.')

    suffix = ''

    if (pos != -1) {

        suffix = filename.substring(pos)

    }

    return suffix;

}

function calculate_object_name(filename)

{

    if (g_object_name_type == 'local_name')

    {

        g_object_name += "${filename}"

    }

    else if (g_object_name_type == 'random_name')

    {

        suffix = get_suffix(filename)

        g_object_name = key + random_string(10) + suffix

    }

    return ''

}

function get_uploaded_object_name(filename)

{

    if (g_object_name_type == 'local_name')

    {

        tmp_name = g_object_name

        tmp_name = tmp_name.replace("${filename}", filename);

        return tmp_name

    }

    else if(g_object_name_type == 'random_name')

    {

        return g_object_name

    }

}

function set_upload_param(up, filename, ret)

{

    if (ret == false)

    {

        ret = get_signature()

    }

    g_object_name = key;

    if (filename != '') { suffix = get_suffix(filename)

        calculate_object_name(filename)

    }

    new_multipart_params = {

        'key' : g_object_name,

        'policy': policyBase64,

        'OSSAccessKeyId': accessid,

        'success_action_status' : '200', //讓服務(wù)端返回200,不然,默認(rèn)會(huì)返回204

        'callback' : callbackbody,

        'signature': signature,

    };

    up.setOption({

        'url': host,

        'multipart_params': new_multipart_params

    });

    up.start();

}

2.3 uploadimages.js

var srcArray = new Array();

var index = 0;

CKEDITOR.dialog.add('uploadimagesDialog', function (editor) {

var testHtml = new CKEDITOR.template('<div></dvi>').output();

return {

title: '圖片上傳',

minWith: 400,

minHeight: 200,

//content是子標(biāo)簽

contents: [

{

id: 'ossimage',

label: '上傳圖片',

//elements是每個(gè)子標(biāo)簽下面的ui元素,如表單元素等

elements: [    //自定義彈窗的內(nèi)容,可以使用模板,也可自定義html及樣式

{

type: 'html',    //圖片上傳成功后的容器

html: '<div id="ossfile"</div>',

style: '',  //對(duì)應(yīng)的樣式

onShow: function () {

//在每次彈窗打開(kāi)的時(shí)候都會(huì)調(diào)用該方法

},

//點(diǎn)擊確定按鈕時(shí),在onOK中調(diào)用commitContent,會(huì)依次觸發(fā)element的commit方法

commit: function (editor) {  //點(diǎn)擊確定按鈕時(shí),將圖片src傳入全局src中

src = $('.imgbox img').attr('src');

},

//點(diǎn)擊確定按鈕時(shí),在onOK中滴啊用superContent,會(huì)依次觸發(fā)element的setup方法

setup: function (editor) {

}

},

{

type: 'html',    //圖片上傳成功后的容器

html: '<a id="postfiles" href="javascript:void(0);" class="btn">開(kāi)始上傳</a>',

style: 'display:none;',  //對(duì)應(yīng)的樣式

},

{

id: 'myimage',    //選擇圖片按鈕

type: 'html',

html: '<div id="container"><a id="selectfiles" href="javascript:void(0);" class="btn">選擇文件</a></div>',  //plupload按鈕

style: 'display:block;width:82px;line-height:34px;background-color:#3366b7;font-size:14px;color:#fff;text-align:center;border-radius:4px;',  //html的樣式,直接作用于上面的a元素

onShow: function () {  //當(dāng)該元素show的時(shí)候執(zhí)行的方法

document.getElementById('ossfile').innerHTML = '';

},

onLoad: function () {

//uploader需要再onLoad方法中定義,因?yàn)橹挥性趏nload的時(shí)候,才能獲取到‘selectfiles’的html元素,uploader才能初始化

var uploader = new plupload.Uploader({

runtimes: 'html5,flash,silverlight,html4',

browse_button: 'selectfiles',

//multi_selection: false,

container: document.getElementById('container'),

flash_swf_url: 'lib/plupload-2.1.2/js/Moxie.swf',

silverlight_xap_url: 'lib/plupload-2.1.2/js/Moxie.xap',

url: 'http://oss.aliyuncs.com',

filters: {

mime_types: [ //只允許上傳圖片和zip文件

{ title: "Image files", extensions: "jpg,gif,png,bmp" },

{ title: "Zip files", extensions: "zip,rar" }

],

max_file_size: '10mb', //最大只能上傳10mb的文件

prevent_duplicates: true //不允許選取重復(fù)文件

},

init: {

PostInit: function () {

document.getElementById('ossfile').innerHTML = '';

document.getElementById('postfiles').onclick = function() {

set_upload_param(uploader, '', false);

return false;

};

},

FilesAdded: function (up, files) {

plupload.each(files, function (file) {

document.getElementById('ossfile').innerHTML +=

'<div style="width:150px;height:150px;border:solid 1px;text-align: center;float:left" id="' + file.id + '">'

+ '<image src="" alt=“占位圖”/>'

+ '</div>';

});

document.getElementById('postfiles').click();

},

BeforeUpload: function (up, file) {

check_object_radio();

set_upload_param(up, file.name, true);

},

//上傳中,這里根據(jù)需要自己寫(xiě)上傳等待,也可在外部實(shí)現(xiàn)

UploadProgress: function (up, file) {

// var d = document.getElementById(file.id);

// d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";

// var prog = d.getElementsByTagName('div')[0];

// var progBar = prog.getElementsByTagName('div')[0]

// progBar.style.width = 2 * file.percent + 'px';

// progBar.setAttribute('aria-valuenow', file.percent);

},

FileUploaded: function (up, file, info) {

if (info.status == 200) {

var imageSrc = get_uploaded_object_name(file.name);

//記?。哼@里要根據(jù)imageSrc最后的圖片名字進(jìn)行從小到大排序,即0.png,1.png這樣子依次插入到數(shù)組中人,然后再根據(jù)輸入插入到富文本編輯器中

//因?yàn)閛ss上傳針對(duì)同個(gè)文件名不能上傳多次,所以在upload.js要針對(duì)文件名進(jìn)行有規(guī)律地自定義

//上傳成功之后顯示圖片縮略圖

srcArray[index] = imageSrc;

index = index + 1;

console.log(document.getElementById(file.id))

document.getElementById(file.id).innerHTML = '<image src="https://XXXX/'+ imageSrc +'?x-oss-process=image/resize,w_150,h_150" alt=“”/>';

}

else if (info.status == 203) {

document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '上傳到OSS成功,但是oss訪問(wèn)用戶設(shè)置的上傳回調(diào)服務(wù)器失敗,失敗原因是:' + info.response;

}

else {

document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response;

}

},

Error: function (up, err) {

if (err.code == -600) {

console.log("\n選擇的文件太大了,可以根據(jù)應(yīng)用情況,在upload.js 設(shè)置一下上傳的最大大小")

// document.getElementById('console').appendChild(document.createTextNode("\n選擇的文件太大了,可以根據(jù)應(yīng)用情況,在upload.js 設(shè)置一下上傳的最大大小"));

}

else if (err.code == -601) {

console.log("\n選擇的文件后綴不對(duì),可以根據(jù)應(yīng)用情況,在upload.js進(jìn)行設(shè)置可允許的上傳文件類型")

// document.getElementById('console').appendChild(document.createTextNode("\n選擇的文件后綴不對(duì),可以根據(jù)應(yīng)用情況,在upload.js進(jìn)行設(shè)置可允許的上傳文件類型"));

}

else if (err.code == -602) {

console.log("\n這個(gè)文件已經(jīng)上傳過(guò)一遍了");

// document.getElementById('console').appendChild(document.createTextNode("\n這個(gè)文件已經(jīng)上傳過(guò)一遍了"));

}

else {

console.log("\nError xml:" + err.response);

// document.getElementById('console').appendChild(document.createTextNode("\nError xml:" + err.response));

}

}

}

});

uploader.init();

}

},

{

//這里只是演示可以通過(guò)在外部寫(xiě)html,然后進(jìn)行展示

id: 'size', 

type: 'html',

html: testHtml,  //html寫(xiě)到了上面

commit: function (editor) {

var tt = document.getElementsByName('size'); //取radio選項(xiàng)

for (var i = 0; i < tt.length; i++) {

if (tt[i].checked) {

imgsize = tt[i].value;

break;

}

}

}

}

]

}

],

onShow: function () {

},

onOk: function () {

//該方法會(huì)依次調(diào)用element數(shù)組中的commit方法,在這里我們不需要在element中做額外調(diào)用,所以不使用,如果需要的話可以開(kāi)啟使用

//this.commitContent(editor);

//點(diǎn)擊確定時(shí),把圖片依次插入

console.log(srcArray);

for (x in srcArray) {

var realImageSrc = "https://XXXXXXX/" + srcArray[x];

var ele = CKEDITOR.dom.element.createFromHtml('<p style="padding:5px 0;"><img style="width:250px;height:250px" src="' + realImageSrc + '"/></p><br/>');

editor.insertElement(ele);  //將element插入editor

}

},

onCancel: function () {

}

}

});

2.4 html
在這里插入圖片描述

3. 效果圖

本來(lái)為大家錄制了一段效果圖,但是gif太大,上傳不了,故作罷

在這里插入圖片描述

四. CKEditor的ACF功能

CKEditor4有個(gè)叫做ACF的功能,能過(guò)濾掉一些標(biāo)簽,如script等,在前端就已經(jīng)組織了大部分的我們覺(jué)得不需要的標(biāo)簽,提高了整個(gè)編輯器的安全性,但是CKEdor4不建議只用這個(gè)功能來(lái)做為安全性的校驗(yàn),后臺(tái)也應(yīng)該做相應(yīng)的校驗(yàn)。但是也是因?yàn)檫@個(gè)功能的存在,導(dǎo)致你在自定義插件的時(shí)候,可能會(huì)遇到一些莫名其妙的問(wèn)題,如標(biāo)簽失效等,這個(gè)時(shí)候可以先把這個(gè)功能個(gè)關(guān)掉,等插件完成后再根據(jù)自己的需要打開(kāi)。

官方對(duì)于ACF的解釋:https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html


//disallowedContent: 'img{width,height,float}',

//extraAllowedContent: 'img[width,height,align]',

allowedContent: 'p abbr[title,id]',

五. 參考文檔

https://liyang0207.github.io/2017/08/22/ckeditor%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%89%E9%92%AE%E5%8F%8A%E9%98%BF%E9%87%8Coss%E4%B8%8A%E4%BC%A0/

https://ckeditor.com/docs/ckeditor4/latest/index.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.背景介紹 在做Web應(yīng)用時(shí),經(jīng)常會(huì)進(jìn)行富文本編輯,常用的富文本編輯器有很多,比如CuteEditor、CKEd...
    維克拉瑪?shù)賮?/span>閱讀 2,319評(píng)論 0 0
  • HTML 5 HTML5概述 因特網(wǎng)上的信息是以網(wǎng)頁(yè)的形式展示給用戶的,因此網(wǎng)頁(yè)是網(wǎng)絡(luò)信息傳遞的載體。網(wǎng)頁(yè)文件是用...
    阿啊阿吖丁閱讀 4,951評(píng)論 0 0
  • 我們做直播的目標(biāo),有人說(shuō)要賺錢(qián)當(dāng)然是無(wú)可后非的,一種免費(fèi)模式,二是付費(fèi)課程,三是先免費(fèi)后付費(fèi)課程,四是體驗(yàn)課程,五...
    安利網(wǎng)紅閱讀 2,500評(píng)論 0 1
  • 今天我開(kāi)車(chē)去上班,同事們一路上有說(shuō)有笑不覺(jué)間就到學(xué)校了,時(shí)間剛剛好! 上午上課很順利。但其中有件事情使我認(rèn)識(shí)到自己...
    華麗的美麗麗閱讀 220評(píng)論 0 0
  • 效果圖: 字母索引這個(gè)功能還是很常見(jiàn)的,例如:聯(lián)系人,城市選擇等一些功能都會(huì)用到,其實(shí)這個(gè)功能還是很簡(jiǎn)單的,現(xiàn)在我...
    波波維奇c閱讀 4,051評(píng)論 0 0

友情鏈接更多精彩內(nèi)容