9102年如何寫一個本身的markdown在線編輯器

Markdown 在線編輯器

先貼出編輯器地址,涵蓋了大多數markdown語法的快捷操做,實時編譯實時預覽,支持直接導出md 格式文件,支持微博圖牀。純前端實現,沒必要擔憂數據被後臺存儲。未作移動端適配,建議pc食用。 歡迎各位有寫做需求的大佬試用,提出寶貴意見。前端

背景 & 前言

市面上一些md編輯器 有的有實時預覽,好比掘金,沒有操做按鈕(有快捷鍵的哈),用着不是太方便,而簡書的操做按鈕有的受限於簡書鑽的數量。事實上有道詞典的md編輯器作的很好,但最近出現了我出現了卡頓、中文難以輸入上去的問題,棄之。
因此乾脆本身擼一個,能夠知足本身寫東西的需求。 本身作的東西就算難用也得受着
因爲手上沒有windows設備,滾動條的樣式還請本身修改下。vue


技術

vue less iview markdown-it iconfontgit


插件

markdown-it-mark 標記功能
markdown-it-emoji emoji表情解析
highligh.js代碼高亮
markdown-it-task-checkbox 複選框功能
markdown-it-footnote 腳註功能github


插件效果

==高亮標記==
:smiling_imp:npm

掘金沒有支持標記emoji,貼一下圖。 windows

原理

在編輯器輸入組件中 watch輸入內容的變化,有變化就實時調用markdown-itrender函數,並在localStorage中實時更新一份,防止頁面誤操做被跳出再返回時辛辛苦苦寫的內容沒了。同時也能夠達到此次沒寫完頁面關閉了,下次打開繼續寫的需求。 導出文件後草稿會被清空。 由於不調用接口存儲數據,未作函數防抖處理,如需引入請自行添加。 微博圖牀的地址是從一個工具頁面上扒下來的,感受寫那個工具的兄弟也是從其餘的地方扒的呢哈哈(開玩笑的),貼出工具地址:圖牀工具瀏覽器


下載打包

git clone git@github.com:ch957869975/md-editor.git
npm run devnpm run build 打開 8080端口便可看到預覽 bash


有意思的點

作的時候遇到幾個點比較有意思,提一下。markdown

在光標位置插入字符

ie 支持document.selection,而絕大多數瀏覽器支持selectionStartselectionEnd 兩個屬性。利用這兩個屬性加上字符串的substring方法動態拼接起來。 這裏須要注意的是 用這個方法拼接起來的字符串,並無觸發對變量的雙向綁定,因此我在這裏手動觸發了一下textarea的input事件,以下:hexo

document.querySelector('textarea').dispatchEvent(new Event('input'))
複製代碼

文件在前端生成並下載

下載在前端開發中並不稀奇,但文件寫入可能不常遇到,要不是寫這個玩意,我也沒作過文件生成。 代碼以下:

if (!this.editorContent || !window.localStorage.getItem('MarkdownDraft')) {
     return this.$Notice.error({ title: '你尚未寫內容' })
 }
const content = this.editorContent
const elem = document.createElement('a');
elem.download = 'draft.md';
elem.style.display = 'none';
const blob = new Blob([content], { type: 'text/plain' });
elem.href = URL.createObjectURL(blob)
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
setTimeout(() => {
   this.editorContent = ''
   window.localStorage.removeItem('MarkdownDraft')
}, 300)
複製代碼

思路仍是比較清晰的:有值的時候才生成, 避免生成一個空文件。 利用Blob對象生成對應內容後,再建立一個 不可見的a標籤並將 hrefdownload屬性添加進去,手動觸發點擊事件後並移除該標籤。 可是須要考慮兼容性呀。 這裏是a.download的支持狀況,ie不支持!!!。

木得辦法,作個判斷吧。

if (!('download' in document.createElement('a'))) return this.$Notice.error({ title: '瀏覽器不支持' })
複製代碼

可能你說ie怎麼辦?
回答:都9102年了,你還在用ie,不拋棄你拋棄誰??


組件通訊

組件之間通訊,由於偷懶,用了bus.js,實際代碼就兩行

import Vue from 'vue'
export default new Vue()
複製代碼

原理是 掛載在同一實例上的組件均可以觸發實例上的事件,理論上是能夠實現任意組件之間的通訊,無視組件層級關係。可是, 並不推薦這種作法,由於這會讓你的邏輯太跳躍,具體表現就是你的代碼東一榔頭西一棒子,A組件在bus上綁定的事件常常找不到在哪裏觸發的,B組件觸發的事件找不到是在哪裏綁定的,維護起來較爲困難。


總結

功能簡單、技術簡單、ui簡單、部署簡單。一個簡單的小項目,就看你願不肯意去作了。

這裏貼出編輯器地址源碼地址厚着臉皮求個star博客地址

不是全部的事情都能如願以償,可是任何事情都值得去嘗試。加油!

ps: 下面兩個腳註對應插件效果演示,沒必要關心。


  1. 腳註1 ↩︎

  2. 腳註2 ↩︎