文本編輯器的前生與今世

文本編輯器的前生與今世

作者:秘塔科技前端工程師 木子舒

文本編輯想必大家都不陌生,從記事本,Word,到瀏覽器裡面的富文本編輯器(Rich Text Editor,簡稱RTE),都是大家在工作中和上網的時候會不斷接觸和使用的.

富文本之所以稱之為「富」,是相較於沒有複雜格式的純文本(Plain Text)而言的.雖然目前大家對能夠所見即所得(WYSIWYG,what you see is what you get)的對文本進行加粗,居中,修改字體,字型大小等功能習以為常,很難想像這樣的功能曾經也算是技術創新,代表先進的生產力?

我們看看,在不太遙遠的1991年,大家日常用的文本編輯軟體WPS是這個模樣:

驚不驚喜?意不意外?

從這個「古典」的界面,大家應該能感受到時代的發展了.目前哪怕是在瀏覽器里運行使用的在線編輯器,除了能正常編輯以外,還可以顯示文字加粗、顏色、鏈接、嵌入的圖像等更多的功能.實現了所見即所得,整個編輯界面簡潔美觀。

實際上整個所見即所得的編輯器發源於施樂(Xerox)公司.從上世紀80年代提出這個概念,到1981年發行 Xerox 8010 Star 附帶的第一款商用所見即所得編輯器 Bravo,施樂公司都走在了時代的最前面,具有極強的先鋒性(堪比趙麗華女士的詩歌).但真正將這發揚光大的,還是著名的喬布斯,以及最近市值已經邁入歷史性的1.1萬億美元的蘋果公司.

施樂公司Xerox 8010 Star的圖形編輯界面

蘋果公司1984年發行的MacWrite 1.0

歷史上,之所以實現一個所見即所得的編輯器如此之困難,一方面是受限於當年的硬體能力,另一方面早期的非圖形操作系統(如DOS)並未提供方便的圖形API,使得開發人員必須從零開始繪製每一個像素.

到如今的網路時代,瀏覽器的功能愈發的強大,我們甚至可以將自己幾乎所有的工作都放在瀏覽器內部完成.在現代瀏覽器中開發一個富文本編輯器的難度如何呢?

答案是令人驚異的簡單.最核心的是對瀏覽器自帶的 execCommand 函數的使用,目前主流瀏覽器都對其有所支持.

基本原理

在瀏覽器展示出來的界面上,要去給某些內容添加類似於加粗、斜體等效果時,瀏覽器中所顯示的文檔直接去調用上述函數就可以實現,即調用函數document.execCommand,而這個函數起作用是基於包含所選內容的標籤自帶的contentEditable屬性的值等於true

舉個例子,假如我有一個標籤 div,我想讓這個 div 標籤內部的一個詞語背景色為紅色,完成這個功能的前提是,這個 div 標籤必須是可編輯的,我們可以設置這個 div 標籤的屬性contentEditable="true"(其值為 bool,表示元素能被編輯),相當於此時這個 div 標籤就是一個 textarea 的文本域,然後再去調用瀏覽器的document.execCommand(aCommandName, aShowDefaultUI, aValueArgument) 函數,這個函數有三個參數,第一個參數為命令,例如:粗體,斜體,背景色等;第二個參數為是否展示用戶界面,一般為 false;第三個參數為一些命令的額外參數,例如:insertImage 需要提供插入 image 的 url,默認值為 null。

案例

我們來看看如何採用幾行代碼,通過 Vue 框架來實現一個富文本編輯器.

首先是 Html 部分,創建 Vue 項目,為了方便,引入 element-ui 相關的文件,整個功能由兩部分組成,一部分是按鈕組,另一部分是一個可編輯的 div。

<el-button-group id="tools-wrap"> <el-button v-for="item in tools" :key="item.index" :label="item.name" @click="changeSelf(item)><img :item.src"/></el-button></el-button-group><div contenteditable="true" id="editor" v-html="content"></div><!--發布文章按鈕--><div class="seditor-footer"><el-button class="submitbtn" type="primary" @click="submitArticle">發布文章</el-button></div>

至於 CSS 樣式部分,大家可根據自己的喜好去調節.下邊是我簡單寫的樣式

#editor { height: 200px; border: 1px solid #ccc; padding: 10px; border-radius: 4px; } #editor:active, #editor:focus{ outline: none; } #tools-wrap .el-button { border: none; border-radius: 0px; } #tools-wrap .el-button:hover { background: #ccc; } #tools-wrap .el-button:focus, #tools-wrap .el-button:active { background: #ccc; } #tools-wrap .el-button img { width: 20px; }

為了方便操作代碼的書寫,在 Vue 中直接定義了一個數組變數來裝所有的操作:

export default { data () { return { content: Click to Editor... tools: [ { index: 1, name: 加粗, property: bold, value: null, src: require(../../static/img/icon/bold.png) }, { index: 2, name: 傾斜, property: italic, value: null, src: require(../../static/img/icon/italic.png) }, { index: 3, name: 下劃線, property: underline, value: null, src: require(../../static/img/icon/underline.png) }, ] } }}

下邊才是整個富文本編輯器的關鍵函數,可憐的幾行代碼,直接調用函數,傳入相應的參數即可.最後將獲取到的 Html 參數傳遞給後台資料庫,進行儲存就可以啦.

methods: { changeSelf: function(param) { document.execCommand(param.property, false, param.value) }, submitArticle: function() { let editor = document.getElementById(editor) let html = editor.innerHTML document.write(html) }}

這樣,一個簡單的富文本編輯器就出現了.是不是很簡單,我們來看看最終的效果.

結語

實際上,這個富文本編輯器是一種最簡單的實現,僅僅是對瀏覽器自帶的 document.execCommand 函數進行的一層封裝,所有的樣式實現都調用了同一個函數.而在當今流行的富文本編輯器中,基本都是將其重寫(對瀏覽器已有函數進行修改完成自己的需求).整個過程很繁瑣和複雜,而且要兼容各個瀏覽器,難度會大大的提高.有興趣的小夥伴們,來嘗試一下重造輪子的成就感吧!


推薦閱讀:

Vim 8 中 C/C++ 符號索引:從 GTags 到 LanguageServer
在無格式中探索格式 - MarkDown 入門指南
VIM學習筆記-開篇
新版移動端編輯器正式上線啦

TAG:文本編輯 | 文本編輯器 | 前端開發 |