渲染與同步
本頁說明 MDViewer 何時重新渲染、渲染時做了哪些事,以及與編輯器的捲動同步如何運作。
觸發時機
| 來源 | 條件 |
|---|---|
編輯器 keyup |
autosave 為真,且按鍵不是方向鍵、Shift、Control、Alt、CapsLock、Escape、F1~F12、Meta |
編輯器格式化方法(bold()、heading() 等) |
autosave 為真 |
undo()、redo() |
autosave 為真 |
clear()、openfile() 讀取完成 |
一律觸發 |
save() |
autosave 為假時觸發(Cmd/Ctrl+S 或工具列「儲存並預覽」) |
直接呼叫 viewer.init(text) |
一律觸發 |
autosave: false 時,輸入不會即時反映到預覽,只有 save() 才會更新。
渲染步驟
viewer.init(txt) 的流程:
- 設
data-saved="1",清除上一個計時器 - 等待
sync.delay毫秒(預設 300;傳0會因 falsy 回到 300) - 決定內容:
txt→ 綁定編輯器的文字 →emptyContent,取第一個非空值 - 呼叫
transToHTML()(擴充模式,帶 hashtag 設定) - 以
replaceChildren()整段替換預覽器內容 - 為每個程式碼區塊的複製按鈕綁定
navigator.clipboard.writeText();成功時加successclass 1 秒,失敗加errorclass - 每 50 ms 檢查 code-prettify 的全域
PR是否載入;載入後還原捲動位置、執行PR.prettyPrint(),再對整份文件的.mermaid元素執行mermaid.run()
連續輸入時計時器會被重設,只有停止輸入超過 sync.delay 才會真正渲染(debounce)。
讀取編輯器文字
預覽器不透過事件拿資料,而是在渲染時讀取編輯器容器中每個 <div> 列的 innerText:空白列變成單一 \n,不換行空白換成一般空白,最後整體 trim()。
捲動同步
sync.scroll 為真時,綁定編輯器的當下會設定編輯器的 onwheel:每次滾輪事件把 deltaY 加到預覽器的 scrollTop。
| 限制 | 說明 |
|---|---|
| 只同步滾輪 | 拖曳捲軸、觸控滑動、鍵盤捲動不會同步 |
| 單向 | 只有編輯器帶動預覽器 |
| 依增量 | 不是比例對應,兩邊內容高度差異大時位置會漂移 |
覆寫 onwheel |
會取代編輯器容器上既有的 onwheel handler |
儲存狀態旗標
編輯器與預覽器容器的 data-saved 屬性反映內容是否已同步:輸入後設為 0(unsave()),渲染開始時設為 1。NanoMD.css 依此屬性顯示狀態,也可用於自訂「未儲存」提示。
虛擬 DOM
vDOM 類別與 #applyPatch() 仍在原始碼中,但目前渲染改用 replaceChildren() 整段替換以確保正確性,diff 與 patch 都沒有被呼叫。