国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

vue項(xiàng)目移植tinymce踩坑

Kosmos / 1116人閱讀

2019-2-18

貌似這篇文章幫了大家一些小忙
最近tinymce出5.0版本了,下面的api還是4.x的,新版本可能會(huì)有些不適用了,最近業(yè)務(wù)繁忙,等哪天周末有時(shí)間的話我再做點(diǎn)更新 :)

前言

最近因業(yè)務(wù)需求在項(xiàng)目中嵌入了tinymce這個(gè)編輯器,用于滿足平臺(tái)給用戶編輯各類(lèi)新聞內(nèi)容什么的業(yè)務(wù)需求,前后也花了不少時(shí)間體驗(yàn)和對(duì)比了市面上各類(lèi)開(kāi)源編輯器。

各大WYSIWYG編輯器的簡(jiǎn)單比較

UEditor: 因?yàn)橐呀?jīng)不再維護(hù)了,需要大量修改源碼,很多都是專門(mén)為jsp等服務(wù)器渲染項(xiàng)目寫(xiě)的代碼需要?jiǎng)h除, 然后越刪越害怕越刪越不敢用,依賴jquery,需要專門(mén)用js去parse編輯完成的內(nèi)容,parse完的內(nèi)容還可能污染全局css,兼容老瀏覽器還不錯(cuò), 但是,我們不怎么考慮兼容IE。所以,告辭。

wangEditor: 中文文檔,上手快,依賴jquery,功能少點(diǎn)要花時(shí)間去寫(xiě)插件,需要多帶帶為圖片上傳功能寫(xiě)個(gè)接口,老項(xiàng)目忙著上線臨時(shí)用過(guò),感覺(jué)并不適合當(dāng)前業(yè)務(wù)這么重的編輯功能于是放棄了。

Quill:api友好, 功能少,需要特定的css去解析文本(這點(diǎn)我不大喜歡),ui好看,適合作為論壇回帖功能使用。

CKEditor: CKEditor目前主流的還是4.x的版本,但是文檔看著很瞎眼實(shí)在是提不起興致去配置,草草用了下就放棄了,5.x版本剛從beta結(jié)束,需要指定專門(mén)的node以及npm版本,雖然功能強(qiáng)大配置靈活ui漂亮不過(guò)目前糟糕的兼容性基本是不可能出現(xiàn)在大眾視野了。

KingEditor: 丑,不喜歡,不愛(ài)用

Draft-js: 知乎最近剛改的文本編輯器就是在draft的基礎(chǔ)上開(kāi)發(fā)的,依賴react, 棄。

Medium-editor: 雖然看著感覺(jué)很酷炫,但是,不適合我們的業(yè)務(wù)場(chǎng)景啊, api也簡(jiǎn)陋可怕。

trix: 嗯,又一個(gè)小而美,放棄

Slate: react,放棄

Bootstrap-wysiwyg: bootstrap, jquery, 放棄

tinymce: 文檔好,功能強(qiáng),bug少,無(wú)外部依賴,大家用了都說(shuō)好,嗯,沒(méi)錯(cuò)就是它了。

編輯器配置方面只要能看得懂英文耍起來(lái)還是比較簡(jiǎn)單的,適配中碰到的大部分問(wèn)題都可以通過(guò)看文檔解決,即便看文檔解決不了網(wǎng)上也有大量的文章能告訴你怎么配置能解決。

當(dāng)然了,主要是我這里需要解決一些別人覺(jué)得超簡(jiǎn)單自己一想都很煩人的需求,比如:

word文檔粘貼進(jìn)來(lái)要帶格式

兼容移動(dòng)端

word文檔粘貼進(jìn)來(lái)要正常顯示并且還要兼容移動(dòng)端

電腦網(wǎng)頁(yè)里粘貼進(jìn)來(lái)內(nèi)容要正常顯示并且排版還不能亂

電腦網(wǎng)頁(yè)拷過(guò)來(lái)的內(nèi)容還要兼容到移動(dòng)端

初始化

因?yàn)閠inymce的Plugins是按需加載的
為了能先快速上手這個(gè)編輯器
就先在vue-cli的index.html中默認(rèn)塞入一條在線cdn地址



記得去下載語(yǔ)言包到本地,
然后就在文件內(nèi)引入

import "./zh_CN.js"

后面有機(jī)會(huì)再寫(xiě)下多帶帶打包的事項(xiàng),畢竟這貨體積還不小。

插入vue組件模板

記得一定要在textarea外面包一層div,不然...你自己試試看就知道了。

組件基礎(chǔ)配置

將tinymce通過(guò)指定的selector掛載到組件中



好了,組件基本的初始化完成,后面正式開(kāi)始踩坑之旅

API

具體內(nèi)容看官網(wǎng)的API就行,英語(yǔ)不好的用chrome翻譯下對(duì)照著demo也能看個(gè)七七八八,當(dāng)然主要原因還是我比較懶。

我這邊根據(jù)自身業(yè)務(wù)需求在組件的data內(nèi)寫(xiě)了個(gè)默認(rèn)配置

DefaultConfig: {
  // GLOBAL
  height: 500,
  theme: "modern",
  menubar: false,
  toolbar: `styleselect | fontselect | formatselect | fontsizeselect | forecolor backcolor | bold italic underline strikethrough | image  media | table | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | preview removeformat  hr | paste code  link | undo redo | fullscreen `,
  plugins: `
    paste
    importcss
    image
    code
    table
    advlist
    fullscreen
    link
    media
    lists
    textcolor
    colorpicker
    hr
    preview
  `,

  
  // CONFIG

  forced_root_block: "p",
  force_p_newlines: true,
  importcss_append: true,

 // CONFIG: ContentStyle 這塊很重要, 在最后呈現(xiàn)的頁(yè)面也要寫(xiě)入這個(gè)基本樣式保證前后一致, `table`和`img`的問(wèn)題基本就靠這個(gè)來(lái)填坑了
  content_style: `
    *                         { padding:0; margin:0; }
    html, body                { height:100%; }
    img                       { max-width:100%; display:block;height:auto; }
    a                         { text-decoration: none; }
    iframe                    { width: 100%; }
    p                         { line-height:1.6; margin: 0px; }
    table                     { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; }
    .mce-object-iframe        { width:100%; box-sizing:border-box; margin:0; padding:0; }
    ul,ol                     { list-style-position:inside; }
  `,

  insert_button_items: "image link | inserttable",

  // CONFIG: Paste
  paste_retain_style_properties: "all",
  paste_word_valid_elements: "*[*]",        // word需要它
  paste_data_images: true,                  // 粘貼的同時(shí)能把內(nèi)容里的圖片自動(dòng)上傳,非常強(qiáng)力的功能
  paste_convert_word_fake_lists: false,     // 插入word文檔需要該屬性
  paste_webkit_styles: "all",
  paste_merge_formats: true,
  nonbreaking_force_tab: false,
  paste_auto_cleanup_on_paste: false,

  // CONFIG: Font
  fontsize_formats: "10px 11px 12px 14px 16px 18px 20px 24px",

  // CONFIG: StyleSelect
  style_formats: [
    {
      title: "首行縮進(jìn)",
      block: "p",
      styles: { "text-indent": "2em" }
    },
    {
      title: "行高",
      items: [
        {title: "1", styles: { "line-height": "1" }, inline: "span"},
        {title: "1.5", styles: { "line-height": "1.5" }, inline: "span"},
        {title: "2", styles: { "line-height": "2" }, inline: "span"},
        {title: "2.5", styles: { "line-height": "2.5" }, inline: "span"},
        {title: "3", styles: { "line-height": "3" }, inline: "span"}
      ]
    }
  ],

  // FontSelect
  font_formats: `
    微軟雅黑=微軟雅黑;
    宋體=宋體;
    黑體=黑體;
    仿宋=仿宋;
    楷體=楷體;
    隸書(shū)=隸書(shū);
    幼圓=幼圓;
    Andale Mono=andale mono,times;
    Arial=arial, helvetica,
    sans-serif;
    Arial Black=arial black, avant garde;
    Book Antiqua=book antiqua,palatino;
    Comic Sans MS=comic sans ms,sans-serif;
    Courier New=courier new,courier;
    Georgia=georgia,palatino;
    Helvetica=helvetica;
    Impact=impact,chicago;
    Symbol=symbol;
    Tahoma=tahoma,arial,helvetica,sans-serif;
    Terminal=terminal,monaco;
    Times New Roman=times new roman,times;
    Trebuchet MS=trebuchet ms,geneva;
    Verdana=verdana,geneva;
    Webdings=webdings;
    Wingdings=wingdings,zapf dingbats`,

  // Tab
  tabfocus_elements: ":prev,:next",
  object_resizing: true,

  // Image
  imagetools_toolbar: "rotateleft rotateright | flipv fliph | editimage imageoptions"
}

因?yàn)楸救吮容^懶,以上配置導(dǎo)出的代碼可能會(huì)有代碼注入的風(fēng)險(xiǎn),建議保存的時(shí)候再前后端都做下注入過(guò)濾,不過(guò)一般數(shù)據(jù)安全問(wèn)題主要還是服務(wù)器那邊的事情?。

后面的圖片上傳可以多帶帶拆出來(lái)做個(gè)小配置,直接寫(xiě)到props里好了。

  url: {
    default: "",
    type: String
  },
  accept: {
    default: "image/jpeg, image/png",
    type: String
  },
  maxSize: {
    default: 2097152,
    type: Number
  },
  withCredentials: {
    default: false,
    type: Boolean
  }

然后把這套東西塞到init配置里

  // 圖片上傳
  images_upload_handler: function (blobInfo, success, failure) {
    if (blobInfo.blob().size > self.maxSize) {
      failure("文件體積過(guò)大")
    }
    
    if (self.accept.indexOf(blobInfo.blob().type) >= 0) {
      uploadPic()
    } else {
      failure("圖片格式錯(cuò)誤")
    }
    function uploadPic () {
      const xhr = new XMLHttpRequest()
      const formData = new FormData()
      xhr.withCredentials = self.withCredentials
      xhr.open("POST", self.url)
      xhr.onload = function () {

        if (xhr.status !== 200) {
          // 拋出 "on-upload-fail" 鉤子
          self.$emit("on-upload-fail")
          failure("上傳失敗: " + xhr.status)
          return
        }

        const json = JSON.parse(xhr.responseText)
        // 拋出 "on-upload-success" 鉤子
        self.$emit("on-upload-complete" , [
          json, success, failure
        ])
      }
      formData.append("file", blobInfo.blob())
      xhr.send(formData)
    }
  }

至此, 一個(gè)組件的封裝基本算是完成了

看下初階成果


直接引入組件調(diào)用就行了


但是作為一名優(yōu)秀的程序員,這怎么可能夠嘛。
下面說(shuō)下打包的事情

塞入webpack

為了加快頁(yè)面載入速度就要首先解決載入文件過(guò)多的問(wèn)題,而大部分時(shí)間用戶并不需要每次打開(kāi)頁(yè)面都先加載一遍editor的核心文件,而editor本身也要按需加載內(nèi)容,一開(kāi)始想把每個(gè)plugin都搞成獨(dú)立組件模塊按需載入,但是這就要涉及到修改編輯器本身源碼,或者說(shuō)對(duì)window.tinymce刪掉點(diǎn)特性,這些都太麻煩也都有風(fēng)險(xiǎn),對(duì)后面的代碼維護(hù)影響也大,索性就都先留著。
后面邊做邊改吧

還是以vue-cli為例
把官網(wǎng)下載的包塞到stataic文件夾中
然后刪掉index.html模版中的cdn代碼吧不需要了
當(dāng)然這里有倆選擇
要么做成一個(gè)異步組件,多帶帶打包,按需載入
要么直接引入到main.js中將包打成為一個(gè)巨無(wú)霸
所以我選擇前者,

首先老規(guī)矩 引入編輯器主體

import "../../static/tinymce/tinymce.min.js"

然后刷新下頁(yè)面,不出意外應(yīng)該是報(bào)這么個(gè)錯(cuò)Uncaught SyntaxError: Unexpected token <
眼尖的朋友應(yīng)該知道是怎么回事了theme.js:1
在默認(rèn)配置下, tinymce載入的theme的路徑居然是這個(gè)
Request URL:http://localhost:8080/themes/modern/theme.js
然后我跑去官網(wǎng)搜了下api 只搜到一個(gè)叫document_base_url的api,但是根據(jù)多年程序員的直覺(jué)經(jīng)驗(yàn)告訴我 不是這貨(嗯,我在這里卡住了),網(wǎng)上翻了下各地文獻(xiàn),都沒(méi)有啊,
那怎么辦呢
于是我就跑去看源碼...但是4萬(wàn)行...算了...
然后我就在控臺(tái)打印了下tinymce對(duì)象,然后發(fā)現(xiàn)了一個(gè)叫baseURLstring對(duì)象,嗯,有希望了。
在源碼里搜了下baseURL
蹦出來(lái)這段代碼 .... 算了有很多段...
大致思想就是通過(guò)當(dāng)前URI拆出來(lái)個(gè)baseURL,改掉就行了

window.tinymce.baseURL = "/static/tinymce"

如果需要載入的地址是另一個(gè)比如自己公司的cdn的路徑,那改成全路徑就行了

window.tinymce.baseURL = "http://cdn.xxx.com/static/tinymce"

貌似路徑的問(wèn)題解決了

但是新的問(wèn)題又出現(xiàn)了,
插件下過(guò)來(lái)都是帶min的,但默認(rèn)載入的插件都是不帶min的,一定是我源碼沒(méi)看仔細(xì),
然后我又搜了一下代碼

if (!baseURL && document.currentScript) {
  src = document.currentScript.src;
  if (src.indexOf(".min") != -1) {
    suffix = ".min";
  }

  baseURL = src.substring(0, src.lastIndexOf("/"));
}

希望就在眼前,貌似是業(yè)務(wù)我載入的方式是直接導(dǎo)入到模塊的,于是一個(gè)叫suffix的默認(rèn)值為空了,于是我去又加了行代碼:

window.tinymce.suffix = ".min"

成功!
你看嘛,超級(jí)簡(jiǎn)單的是不是,根本不用改源碼,網(wǎng)上說(shuō)的動(dòng)不動(dòng)就去改源碼什么的不要信啊不要信,大部分面向?qū)ο蟮氖虑楦膫€(gè)默認(rèn)值就行了。

對(duì)了,還記得前面的語(yǔ)言包嘛,
下過(guò)來(lái)塞到/static/tinymce/langs文件夾里
然后刪掉

import "./zh_CN.js"

這行代碼
DefaultConfig中放入一個(gè)新配置項(xiàng)

language: "zh_CN"

好了,后面就是模塊打包的事情了,

打包

前面打的包有一個(gè)問(wèn)題是默認(rèn)配置是載入tinyMce本體,那么就會(huì)造成這個(gè)包大概有500k的體積,如果這個(gè)組件不做異步載入的處理,那么對(duì)于某些業(yè)務(wù)來(lái)說(shuō)就是災(zāi)難。雖然這么做打開(kāi)只用載入一個(gè)文件,業(yè)務(wù)比較穩(wěn)定。
但我覺(jué)得這樣不優(yōu)雅所以最后還是把它多帶帶拎出來(lái)了。
同理,根據(jù)這個(gè)庫(kù)本身的特性,我們完全可以把這么多個(gè)必須的plugin按需要直接統(tǒng)一打成一個(gè)包,直接載入。這樣,我們就又多了一個(gè)幾百k的plugins包。
然后把plugins包和tinyMce主體包在不阻塞頁(yè)面加載的情況下,做個(gè)懶加載提前緩存好文件方便后面使用,而組件本身在掛載前做個(gè)監(jiān)聽(tīng)window.tinymce全局變量的方法,然后cdn控制下文件的過(guò)期時(shí)間即可。
這樣,在保證了靈活度的前提下也保證了業(yè)務(wù)載入的速度。

完,感謝閱讀。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/92314.html

相關(guān)文章

  • vue 集成富文本tinymce

    摘要:開(kāi)發(fā)環(huán)境開(kāi)發(fā)語(yǔ)言插件安裝可以使用里面的文件,下載后可以在里面查看如下未目錄結(jié)構(gòu)可以將整個(gè)結(jié)構(gòu)拷在里面,為了節(jié)省打包后的文件大小可以將以方式導(dǎo)入放在中附上封裝的代碼可以直接導(dǎo)入使用引入中文包地址可導(dǎo)入文件進(jìn)行上傳圖片構(gòu)造的選擇器可以把下面的 開(kāi)發(fā)環(huán)境 1. vscode 開(kāi)發(fā)語(yǔ)言 1. vue 2. javaScript 插件安裝 1. npm install tinymce -S ...

    qpal 評(píng)論0 收藏0
  • 手摸手,帶你用vue擼后臺(tái) 系列三(實(shí)戰(zhàn)篇)

    摘要:社區(qū)的認(rèn)可目前已經(jīng)是相關(guān)最多的開(kāi)源項(xiàng)目了,體現(xiàn)出了社區(qū)對(duì)其的認(rèn)可。監(jiān)聽(tīng)事件手動(dòng)維護(hù)列表這樣我們就簡(jiǎn)單的完成了拖拽排序。 完整項(xiàng)目地址:vue-element-admin 系類(lèi)文章一:手摸手,帶你用vue擼后臺(tái) 系列一(基礎(chǔ)篇)系類(lèi)文章二:手摸手,帶你用vue擼后臺(tái) 系列二(登錄權(quán)限篇)系類(lèi)文章三:手摸手,帶你用vue擼后臺(tái) 系列三(實(shí)戰(zhàn)篇)系類(lèi)文章四:手摸手,帶你用vue擼后臺(tái) 系列...

    Channe 評(píng)論0 收藏0
  • 手摸手,帶你用vue擼后臺(tái) 系列三(實(shí)戰(zhàn)篇)

    摘要:社區(qū)的認(rèn)可目前已經(jīng)是相關(guān)最多的開(kāi)源項(xiàng)目了,體現(xiàn)出了社區(qū)對(duì)其的認(rèn)可。監(jiān)聽(tīng)事件手動(dòng)維護(hù)列表這樣我們就簡(jiǎn)單的完成了拖拽排序。 完整項(xiàng)目地址:vue-element-admin 系類(lèi)文章一:手摸手,帶你用vue擼后臺(tái) 系列一(基礎(chǔ)篇)系類(lèi)文章二:手摸手,帶你用vue擼后臺(tái) 系列二(登錄權(quán)限篇)系類(lèi)文章三:手摸手,帶你用vue擼后臺(tái) 系列三(實(shí)戰(zhàn)篇)系類(lèi)文章四:手摸手,帶你用vue擼后臺(tái) 系列...

    zgbgx 評(píng)論0 收藏0
  • iView 發(fā)布后臺(tái)管理系統(tǒng) iview-admin,沒(méi)錯(cuò),它就是你想要的

    摘要:簡(jiǎn)介是基于,搭配使用組件庫(kù)形成的一套后臺(tái)集成解決方案,由前端可視化團(tuán)隊(duì)部分成員開(kāi)發(fā)維護(hù)。遵守設(shè)計(jì)和開(kāi)發(fā)約定,風(fēng)格統(tǒng)一,設(shè)計(jì)考究,并且更多功能在不停開(kāi)發(fā)中。 showImg(https://segmentfault.com/img/remote/1460000011603206); 簡(jiǎn)介 iView Admin 是基于 Vue.js,搭配使用 iView UI 組件庫(kù)形成的一套后臺(tái)集成解...

    HackerShell 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<