使用 Angular2+ 開發 Markdown 編輯器

2021-03-02 GitBook社區


本文來自作者 孫亖 在 GitChat 上分享 「使用 Angular2+ 開發 Markdown 編輯器」

編輯 | 弗利薩

前言

一直想寫一個 Angular2+ 的分享,但是沒有一個好的切入點。前段時間我向分享 Chat 的白宦成老師請教 Markdown 的問題,他向我推薦 Typora 編輯器,我覺著這就是我一直想要的 Markdown 編輯器,於是我就想到了這個主題。

當然,我的水平一時是難於寫出 Typora 那樣的編輯器的,但人生已經如此艱難,大家就不要拆穿了,我主要是想通過一個實際應用分享一下 Angular(文中提到的 Angular 指的都是Angular2+,實際版本是 Angular5)的開發過程,主要內容包括:

Angular 項目建立

Angular 中的服務

Angular 中使用第三方傳統庫

打包桌面版本

製作一個安裝程序

Angular 項目的默認語言是 TypeScript,如果你不太熟悉請看我的另外一個Chat:TypeScript 快速入門

項目初始化

說了一大堆,我們是要使用 Angular 來開發一個新的項目,如果你以前沒安裝過,那麼你需要先安裝 Node 和 npm。然後使用下面的命令來安裝 Angular/Cli,我們是通過 Angular/Cli 進行項目的管理。

npm install -g @angular/cli

如果你已經安裝過老版本的 Angular/Cli,建議你使用下面的命令,升級到最新的版本。

npm uninstall -g @angular/clinpm cache clean# if npm version is > 5 then use `npm cache verify` to avoid errors (or to avoid using --force)npm install -g @angular/cli@latest

升級過程中可能會報錯誤,類似於:

npm WARN ajv-keywords@3.1.0 requires a peer of ajv@^6.0.0 but none is installed. You must install peer dependencies your
self.

npm ERR! code EINTEGRITY
npm ERR! sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= integrity checksum failed when using sha1: wanted sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= but got sha1-D6HriBx1DgZRGWjwAGT4GuPfJE4=. (988 bytes)

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\sunjipeng\AppData\Roaming\npm-cache_logs\2018-02-21T06_26_16_216Z-debug.log

我們可以手動刪除解決:

刪除用戶目錄下./npmrc。

刪除 Roaming 目錄下 npm 和 npm_cache。

接下來我們要用下面的命令,新建一個項目:

ng new ngMDEditor

新建項目後,有可能因為大區域網的原因,部分依賴未成功安裝,可以通過 npm i 完成安裝,安裝之後,可以通過如下命令,運行預覽調試:

ng serve

先添加個依賴

首先,我是一個前端渣渣;其次,開源世界有很多現成的東西供我們使用,不需要我們再花精力在我們不熟悉的領域。

現在我們依賴別人,以後依賴人工智慧,最後會不會替代?

要做一個 Markdown 編輯器,首先需要解析 Markdown,根據 Github 上 most stars 排序,JavaScript 類的 marked 排第一,網上用的人也比較多,但是我喜歡另外一個 markdown-it,主觀感覺特性豐富,而且插件比較多,有 MathJax 的插件,挺好用的。

我們先安裝 markdown-it,使用 npm 命令如下:

npm install markdown-it --save

因為 Angular 默認使用 Typescript,通常我們需要編寫聲明文件告訴 TypeScript 我們的 JavaScript 庫的存在,很多庫已經有現成的聲明文件,所以,使用 npm 安裝一下:

npm install --save @types/markdown-it

另外,我需要界面布局,前面說了,我是前端渣渣,所以我常常使用其他工具來布局和寫界面,我用得最多的就是 Bootstrap。

雖然這很不 Angular,還非常的 jQuery,但不得不承認如今這幾種框架混用的現象是非常普遍的。我們先安裝 Bootstrap,同樣使用 npm 命令:

npm install bootstrap

由於 Bootstrap 還依賴 jQuery 和 popper.js,所以我們用同樣的方法安裝這兩個:

npm i jquery popper.js

我們在根目錄下,打開 .angular-cli.json,編輯 scripts 項如下:

 "scripts": [    "../node_modules/markdown-it/dist/markdown-it.min.js",    "../node_modules/jquery/dist/jquery.min.js",    "../node_modules/popper.js/dist/umd/popper.min.js",    "../node_modules/bootstrap/dist/js/bootstrap.min.js"  ],

這樣就算把這些第三方庫加入到框架中了,注意那個 poper 使用的是 umd 庫,用錯了不行,我們也可以在 index.html 中使用傳統方式引入,但這樣更專業一些,Bootstrap 還包含了樣式,我們修改上述文件的 styles 項如下:

"styles": [    "styles.css",    "../node_modules/bootstrap/dist/css/bootstrap.min.css"],

類似的,我們可以在 styles.css 中引入項目文件,例如:

@import "~bootstrap/dist/css/bootstrap.min.css";

主界面開發

接下來,我們就正式開始編寫一個 Markdown 語法的編輯器,借用流行的左右兩欄模式,左邊是 Markdown 語法,右邊是解析渲染後的樣子。我們用 Angular/Cli 命令行工具生成一個 component,也就是這個編輯器:

ng g c page/Editor

上面 ng 就是 Angular/Cli 的命令行工具,參數 g 是 generator 的簡寫,c 是 component 的簡寫,合起來意思就是生成一個組件,最後的參數就是組件的名稱和位置(相對於源碼)。好了,這是自動生成四個文件:

editor.component.css

editor.component.html

editor.component.spec.ts

editor.component.ts

看後綴我們知道 css 是樣式,html 是頁面,ts 是業務邏輯。我們先來把頁面寫出來:

<div class="container d-flex h-100 p-3 mx-auto flex-column">  <div class="row h-100">    <div class="col-6">      <textarea class="h-100 w-100">這是左邊</textarea>    </div>    <div class="col-6">      <p>        這是右邊      </p>    </div>  </div></div>

我不想詳細講太多 HTML 頁面知識,總之就是左邊一個文本輸入框,右邊在 p 元素內將頁面渲染出來。

雙向綁定

我們要把文本區域的內容獲取,傳統的做法就是通過 getElementById 等方法獲取元素,然後根據不同元素的屬性獲取值,大多數時候使用 getElmentById(id).getValue()。

但是,我們現在不是傳統做法,用的是 Angular,可以使用雙向綁定。

雙向綁定說白了就是元素值和業務代碼裡的某個變量或方法是雙向流通的,詳細的內容可以參考官方文檔,但常用的方法我要說一下,方括號 [] 就是代碼值傳到頁面,圓括號 () 就是頁面值傳到代碼,事件就是頁面傳到代碼。

當只有一種括號時是單向綁定,兩種括號一起用時就是雙向綁定。例如:

<input type="text" [(value)]="srcTxt"/>

對於 form 控制項,更常用的是 ngModel,使用 ngModel 前我們需要在 module 中引入 FormsModule:

 imports: [    BrowserModule,    FormsModule  ],

基於我們前面的需求,現在代碼中新增一個屬性 srcTxt 保存文本區域輸入的 Markdown 代碼:

srcTxt:string = "源文件"

然後,在頁面上通過 ngModel 綁定此屬性:

<textarea class="h-100 w-100" [(ngModel)]="srcTxt">這是左邊</textarea>

解析 Markdown 並顯示

我們現在通過 srcTxt 獲取了 Markdown 源碼,接下來我們通過 Markdown-it 解析出結果並顯示出來。

前面我們已經添加了 Markdown-it 的類型庫,現在我們引入它就可以使用:

import * as MarkdownIt from 'markdown-it'

當 Markdown 源碼改變時,我們需要重新解析源碼,因此在頁面添加監聽 ngModel 的改變:

<textarea class="h-100 w-100" [(ngModel)]="srcTxt"  (ngModelChange)="srcChanged($event)">這是左邊</textarea>

在邏輯代碼中實現這個監聽,解析源碼為 HTML 格式:

 srcChanged($event) {    var md = new MarkdownIt();    this.outTxt = md.render($event)  }

這裡的 outTxt 是我們定義的一個結果屬性,通過頁面將這個結果展現出去,頁面就完成了。

<div [innerHTML]="outTxt"></div>

另外一種方式是使用 pipe,Angular 裡面 pipe 的目的就是將輸入的值轉換為目標值,比如時間、貨幣、數字的格式化等。我們先寫一個 Markdown 解析轉換的 pipe,先生成一個:

ng g pipe pipe/Md

Angular 中內置了一些 pipe,也可以自定義 pipe,我們修改生成的 pipe,這裡的代碼很簡單:

 transform(value: any, args?: any): any {    var md = new MarkdownIt();    return md.render(value);  }

相應的,界面上需要根據 pipe 的用法改變:

<div class="col-6">    <span>                                        <div [innerHTML]="srcTxt | md"></div>    </span></div>

支持數學公式

首先,我們從這裡下載一個 MathJax 的庫,本來 Markdown-it 有 MathJax 的擴展,但是使用起來也有各種問題,就只好直接使用 MathJax 官網庫,但編譯後提示有文件找不到,最後就找了這麼一個單文件庫,總算可以了。直接加載文件是這樣配置 .angular-cli.json 的:

     "scripts": [          ...        "./assets/MathJax.min.js"      ],

導入庫後需要配置,由於我們不是用 npm 導入的,也沒有類型庫,所以我們先定義以下,然後再配置:

declare var MathJax:any  ngOnInit() {    MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});  }

這次我們編寫一個 directive 來實現這個功能,本來我打算通過 pipe,或者監聽文本變化用 MathJax 解析公式,但是由於 MathJax 解析方法不太好實現,所以我們用 directive:

ng g directive directive/MathJax

directive 代碼如下:

import { Directive, Input, ElementRef } from '@angular/core';declare var MathJax:any@Directive({  selector: '[MathJax]'})export class MathJaxDirective {  @Input('MathJax') fractionString: string;  constructor(private el: ElementRef) { }  ngOnChanges() {    this.el.nativeElement.innerHTML = this.fractionString;    MathJax.Hub.Queue(["Typeset", MathJax.Hub, this.el.nativeElement]);  }}

最後,我們在標籤上使用 directive 來處理公式:

<div [MathJax]="outTxt"></div>

這是我們輸出公式就可以正常顯示了。

保存編輯到資料庫

這一節我們主要是想講 Angular 使用 HttpClient 與遠程伺服器通訊的功能,這是技術上的,從功能上我們還可以將各種功能進行設計,在 Angular 中可以將它們抽象成服務,新建一個服務如下:

ng g s service/Md

通過上面的命令,我們在 Service 目錄下新建了一個 Md 服務,我們要在這個服務中,添加一個將 Markdown 文檔保存到伺服器的功能。

Angular 通過 HttpClient 來和遠程服務通訊,HttpClient 也是一個服務,要是用這個服務我們首先要在 app.module.ts 中導入 HttpClientModule,app.module.ts 變成了如下內容:

@NgModule({  declarations: [    ...  ],  imports: [    ...    HttpClientModule,    ...  ],  providers: [],  bootstrap: [AppComponent]})export class AppModule { }

然後,我們將 HttpClient 注入到要使用的地方,這裡具體就是 Md 服務:

import { Injectable } from '@angular/core';import { HttpClient } from '@angular/common/http';@Injectable()export class MdService {  constructor(private http:HttpClient) { }}

現在,我們就可以通過 HttpClient 來保存數據了,新建一個服務方法:

save(id:number, title:string, content:string) {    return this.http.post("http://localhost:8080/post", {id: id, title:title, content:content})}

有了服務之後,我們需要在界面中調用它,首先,需要在 app.module.ts 的 providers 中定義:

@NgModule({  declarations: [    AppComponent,    EditorComponent,    MdPipe  ],  imports: [    BrowserModule,    FormsModule,    HttpClientModule  ],  providers: [MdService],  bootstrap: [AppComponent]})    export class AppModule { }

同樣和 HttpClient 一樣,我們需要在使用的地方注入它,我們在 Editor 頁面新建一個按鈕事件:

 <div class="row">      <button type="button" class="btn btn-primary" (click)="doSave()">保存</button>  </div>  <div class="row">      <input type="text" [(ngModel)]="title">  </div>

按鈕點擊通過圓括號綁定到 doSave 方法,doSave 方法通過注入的 Md 服務保存內容到伺服器:

 constructor(private mdSvc:MdService) { }  doSave() {    this.mdSvc.save(null, this.title, this.srcTxt).subscribe(data=> {      alert("保存成功")    }, err => {      alert("保存失敗")    })  }

我這裡僅演示一下,服務使用的是我前面的 Chat:Kotlin開發SpringBoot之Data JPA,有請興趣的朋友可以閱讀該 Chat,另外一個編輯器的功能不單是保存,還有打開等功能,就留作大家的作業吧。

Electron 打包成桌面應用

現在前端的發展其實是很快的,網頁、桌面、手機一網打盡了,Angular 的主頁寫的就是一種框架,適於多個平臺。

把 JavaScript 項目打包成桌面,現在主流有兩種方案 NW.js 和 Electron,我查找學習的資料大多是 Electron,所以這裡我們來看看如何用 Electron 把 Angular 項目打包成桌面應用。

Electron 打包桌面應用說白了就是網頁套個殼,高級點可以提供 API 訪問本地原生功能,基於此,我們甚至可以給一個網站做個桌面應用,我們先初始化一個 npm 的空項目:

掃描下方二維碼

閱讀完整原文

相關焦點

  • 使用Atom打造無懈可擊的Markdown編輯器
    安裝Atom下載安裝Atom:https://atom.io/2. 增強預覽(markdown-preview-plus)Atom自帶的Markdown預覽插件markdown-preview功能比較簡單,markdown-preview-plus對其做了功能擴展和增強。支持預覽實時渲染。
  • 打造一款基於monaco-editor及markdown-it的Markdown編輯器(上)
    ;基於騰訊云云開發 cloudBase 的圖片拖拽上傳功能;接下來我將針對 Monaco editor、 markdown-it 的使用以及相應功能點進行展開前期準備根據 Markdown 的基本布局,在 UI 層,我們將 Markdown 布局方面主要劃分為:菜單欄、編輯區、預覽區
  • 使用逐浪CMS做網站如何引用Markdown編輯器
    Markdown是一種可以使用普通文本編輯器編寫的標記語言,通過簡單的標記語法,它可以使普通文本內容具有一定的格式。MarkDown擁有幾十種特性功能:1、實現渲染效果2、實時同步預覽3、工具欄語法輔助4、更好的中文支持和優化5、獨立的編輯模式
  • MarkDown使用教程(In Atom)
    其實嚴格來說,MarkDown沒有專門的編寫工具,通過簡單的文本編輯器即可編寫MarkDown文本,比如Windows的記事本。但簡單的文本編輯器功能欠缺,沒有高亮的文字表現,更沒有文本效果可言,就像沒有人用記事本寫代碼一樣,最起碼也得用個Edit Plus。
  • 推薦 6 款 macOS 上牛拜的 Markdown 編輯器
    HaroopadHaroopad 是一款免費的、開源的 Markdown 編輯器,可以用來創建面向 Web 的文本。可以使用 Haroopad 來組織不同類型的內容,如幻燈片,報告,博客和演示文稿等。Ulysses 強大的發布功能非常易於使用,可以在 WordPress 或 Medium 等網站上方便地發布文章。更重要的是還可以將所有最終文檔導出為其他格式,例如 RTF,HTML,DOCX 和 ePub 等。
  • MarkDown編輯器
    WORD或者富文本編輯器,But,當我們辛辛苦苦寫了一篇文章,但因為格式,顏色等因素給人不舒服的感覺,就想換一個編輯器了,所以,查看網際網路各個便器器,發現MarkDown編寫最為簡單、好看,所以就整理了各個MarkDown編輯器,如果小夥伴們需要編輯軟體,都可以去官網下載哦。
  • 推薦十大最受歡迎的markdown編輯器!
    它是一款功能強大的編輯器,支持諸如數學和圖表之類的Markdown高級功能以及多種導出選項。2.DraftVisual Studio Code並非是專用的Markdown編輯器,但具有完全相同的功能。通過並排的HTML預覽和擴展來個性化您的書寫體驗,Visual Studio Code是開發人員的可靠選擇。
  • 我的前端故事----優美的編輯器GitHub Atom
    grunt-runner:作為一個前端,grunt相信大家都聽說過,因為這個插件你就可以直接在編輯器裡面操作你的grunt任務了。git-plus:雖然原生的Atom就支持了git命令,但是這個插件會讓你更加喜歡在Atom中使用git,這非常方便在Windows上使用git的同學。
  • 神級編輯器 Vim 使用-插件篇
    ', \ 'ctagsbin' : '~/.vim/plugged/markdown2ctags/markdown2ctags.py', \ 'ctagsargs' : '-f - --sort=yes ', \ 'kinds' : [ \ 's:sections', \ 'i:images' \ ]
  • 打造一個優雅的微信文章編輯器
    之前訪問了下百度和404搜尋引擎,總結一下大家提供的方法,無非是三種:下載Chrome瀏覽器插件 MarkdownHere,在上面先自定義好自己想要的css樣式,然後再微信富文本編輯器上用 markdown語法寫好文章內容,再一鍵轉換,但你會發現,效果差強人意;使用第三方平臺的微信排版器,如下圖:  非常蛋疼是,基本上是卡片式寫作,每寫一段就要拖動出來一個新的卡片容器
  • 物聯網開發筆記——嵌入式開發之Linux系統Vi編輯器的使用
    嵌入式開發學習C語言打下基礎。本節介紹《Linux系統中Vi編輯器的使用》。Linux下Vi編輯器簡介下的文本編輯器有很多種,vi 是最常用的,也是各版本Linux的標配。注意,vi 僅僅是一個文本編輯器,可以給字符著色,可以自動補全。Vim 是 Vi improved 的縮寫,是 vi 的改進版。
  • Github工具分享之易使用可擴展的MarkDown編輯器Markdown Monster
    介紹Markdown Monster是一款易於使用且可擴展的Markdown Editor,Viewer和Windows Weblog Publisher。我們的目標是為Windows提供最佳的Markdown特定編輯器,並儘可能輕鬆地創建Markdown文檔。
  • Seafile Markdown 編輯器介紹 -- 更好用的 Markdown 所見即所得編輯器
    Seafile 從 6.3 版本開始加入了所見即所得的 Markdown 編輯器,又在 7.0 版本對它進行了大幅的改進,並把它作為 Seafile 知識管理功能的基礎,可以使用 Markdown 語法編輯 Wiki 文檔內容。這裡我們對其他的 Markdown 編輯方案進行一下對比,然後再對 Seafile 的 Markdown 編輯器功能進行介紹。
  • 國產新一代前端開發工具—HBuilderX
    HBuilder開發工具,不知道你用過或者聽過沒有,小編之前就用過HBuilder開發過app,確實簡單快捷,這裡就不做介紹。HBuilder是DCloud(數字天堂)推出的一款支持HTML5的Web開發IDE。HBuilder的編寫用到了Java、C、Web和Ruby。HBuilder本身主體是由Java編寫。
  • Python開發之編輯器匯總
    Python開發前言在Python開發中編輯器相信各位小夥伴們都不陌生,但是都哪些編輯器比較好用呢?在本文將匯總四種最好用的編輯器,跟隨小編一起來看看都有哪四種吧。正文1、Sublime Text這是一個輕量級的代碼編輯器,跨平臺,支持幾十種程式語言,包括Python,Java,C/C++等,小巧靈活,運行輕快,支持代碼高亮、自動補全、語法提示,插件擴展豐富,是一個很不錯的代碼編輯器,配置相關文件後,可直接運行python程序:2、VS Code這是微軟開發的一個跨平臺的代碼編輯器,支持常見的程式語言開發,插件拓展豐富,不僅智能補全
  • Angular 10正在接近終點線:帶來哪些顛覆性變化
    Angular LanguageServiceAngular Language Service是一個集成到代碼編輯器中的分析引擎,它提供了一種獲取完整、跟蹤引用、錯誤、提示和導航的方法。它可以在單獨的HTML文件中使用外部模板,也可以使用內聯模板。
  • Typora:簡單高效的 Markdown 編輯器
    在過去兩年多的時間裡,我幾乎每天都使用 Typora 寫作,日記、工作、博客等等都是使用 Typora 寫的。我也曾嘗試過換用其它的編輯器,甚至一些收費的,但最終還是回到了 Typora 的懷抱。不為別的,就因為它太好用了,我已經習慣了它的便捷和高效。可以說 Typora 已經成為了我工作生活的一部分,它讓我更加專注的寫作,它的快捷操作和實時預覽甚至都可以讓我忘了 Markdown 語法。
  • 推薦10款最好的Python開發編輯器
    2.Eclipse with PyDevSublime Text 是開發者中最流行的編輯器之一,多功能,支持多種語言,而且在開發者社區非常受歡迎。Sublime 有自己的包管理器,開發者可以使用TA來安裝組件,插件和額外的樣式,所有這些都能提升你的編碼體驗。
  • 基於jsoneditor二次封裝一個可實時預覽的json編輯器組件react版
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言做為一名前端開發人員,掌握vue/react/angular等框架已經是必不可少的技能了,我們都知道,vue或react等MVVM框架提倡組件化開發
  • 易讀易寫的Markdown,作數學筆記很容易,10分鐘就能掌握
    目前,流行的Markdown編輯器可謂是五花八門,那麼在選擇編輯器之前,請先看幾個問題:支持的系統平臺(Windows、Mac、Linux)?是否免費開源?是否支持中文界面?是否支持數學公式渲染、Mermaid流程圖?是分屏預覽,還是所見即所得的實時預覽?