大家好,今天的篇章要介紹的是 Draft.js
會延續前一天的專案結構接續下去進行修改,如果沒有參與到昨天的建置過程,這邊也有提供原始碼
https://github.com/littlehorseboy/typescript-react/tree/day16-react-intl-useintl-usecontext
可以用 React 的 state render 機制來建立 rich text editors,基礎是建立 HTML 的 contenteditable 上,contenteditable 可是在 IE 5.5 時就已經實裝上去了,據說各家瀏覽器實作都有一些差異,Facebook 的團隊就開發出了這款可以弭平瀏覽器實踐 contenteditable 的差異,並且能用 React 的設計思維來操控 contenteditable 所有的內容變化,內容以外的像是滑鼠點擊任意位置時,按鍵控制等等,可能這些操作很一般,draft.js 的 state 就是會通通幫你紀錄下來,就能夠做得到更複雜的編輯器互動
首先就還是先安裝下來
npm i draft-js
npm i -D @types/draft-js
新增一個 component 來簡單的應用一下
第 5 行,一定要使用 draft.js 提供的 EditorState.createEmpty() 來設定初始值
第 7 行,所以 onChange 掛的事件也是傳進 EditorState 型態
所有操作都會環繞著 [editorState, setEditorState]
這個 state
然後要改 Router 相關的設定,讓頁面多長一顆按鈕可以切換顯示 draft.js 的應用
執行結果
當然我們一定要了解看看 EditorState 它的內容到底有什麼變化
來放一個 console.log 用的 Button
第 13 行,editorState.getCurrentContent()
會取回 ContentState,這邊我們就只關心輸出的內容,還有利用 convertToRaw()
這個 draft.js 提供的函數,才能夠 log 出人比較能看得懂的結構
可以看到 text 紀錄著剛剛敲上去的 abc
接著再從頁面上修改一點內容,我要按下一次 Enter 然後輸入 efg
log 觀察看看 ContentState
此時 blocks 就變為兩個內容
筆者會將這些全部轉成 JSON 儲存到某個地方(可能是資料庫),就能從某個地方取回來載入進 Editor
到這邊為止,算是要讓讀者能夠了解修改的 Editor 的內容後,draft.js 為你做的變化,每個動作改變後的內容都會長在這個 ContentState 裡,最後就是把 ContentState 給 JSON.stringfy 儲存到某個地方,就可以直接拿回來載入
讓我來調整一下 DraftJsPractice.tsx 換個方式呈現後說明
這裡我在 useState 時改變了預設值
放了一個 textarea 來將 convertToRaw(editorState.getCurrentContent())
的內容給扔上去,我想要先直接改動結構中的 text 來改變 ContentState 的內容
與 convertToRaw 相反,使用 convertFromRaw 將 JSON 給 setEditorState
執行結果
改變 Editor 的內容時
改變 textarea 的內容時
到目前為止,應該就能觀察出要如何存取 editorState 的內容,必須要依照 editorState 所需的格式來做轉換,轉換方式就是剛剛的程式碼中用到的那一堆
以上就是筆者在使用 Draft.js 一點小小心得,不過呢,這樣也還不算是編輯器呢,還有那些切換粗體、斜體、改 font-family、font-size、改成超連結,以及增加圖片等等的功能,留待下回揭曉
最後附上原始碼
https://github.com/littlehorseboy/typescript-react/tree/day17-draft-js
明天會繼續介紹 Draft.js 的更多功能,讓它更像一個文字編輯器