draft.js
by Andrey Semin
通過安德烈·塞米(Andrey Semin)
如何使用快捷方式在Draft.js中創建有序列表和無序列表 (How to create ordered and unordered lists in Draft.js with a shortcut)
We at Propeller have encountered many differences between Draft.js and popular text editors. We also found some issues like controlling list depth and multiline items in lists. The biggest difference is the inability to use shortcuts to start a list by default. Surprisingly enough you need to implement this logic yourself.
Propeller的我們在Draft.js和流行的文本編輯器之間遇到了許多差異。 我們還發現了一些問題,例如控制列表深度和列表中的多行項目。 最大的區別是默認情況下無法使用快捷方式啟動列表。 令人驚訝的是,您需要自己實現此邏輯。
As always, there is a plugin available to add support for the shortcuts you use. I also want to refer to draft-js-autolist-plugin as a source of inspiration. For some reason, this plugin didn’t work when we tried it. So we’ve come up with our own solution which is now presented in this post.
與往常一樣,有一個插件可用于添加對您所使用快捷方式的支持。 我也想參考draft-js-autolist-plugin作為靈感來源。 出于某種原因,當我們嘗試該插件時無法使用。 因此,我們提出了自己的解決方案,該解決方案現在將在本文中介紹。
問題 (The problem)
Open Google Docs, Word365, or whatever editor you use. Try to type *
and then type space
. Boom! You’ve started an unordered list. Nice feature to have, right?
打開Goog??le文檔,Word365或您使用的任何編輯器。 嘗試鍵入*
,然后鍵入space
。 繁榮! 您已經開始了無序列表。 不錯的功能,對不對?
If we try the exact same trick with the default Draft.js configuration, we will get nothing but plain text.
如果我們使用默認的Draft.js配置嘗試完全相同的技巧,則只會得到純文本。
Let’s change it!
讓我們改變它!
解 (Solution)
To implement this feature, we need to keep track of the last three pressed buttons. Why three? Well, that’s because the longest character combination we need to support is 1. + space
which is exactly three presses.
要實現此功能,我們需要跟蹤最后按下的三個按鈕。 為什么是三個? 好吧,這是因為我們需要支持的最長字符組合是1. + space
,正好是三按。
To start, let’s implement the logic to store these presses. Here we would use a simple array named history
. This array will store the value of the key that was pressed. We definitely don’t want to process any key presses with modifiers like shift
, alt
and so on. We can use Draft.js built-inKeyBindingUtil.hasCommandModifier
function to perform the check for any modifier.
首先,讓我們實現存儲這些印刷機的邏輯。 在這里,我們將使用一個名為history
的簡單數組。 該數組將存儲所按下鍵的值。 我們絕對不希望使用shift
, alt
等修飾符來處理任何按鍵。 我們可以使用Draft.js內置的KeyBindingUtil.hasCommandModifier
函數執行對任何修飾符的檢查。
Draft.js exposes a keyDown
event for us in the keyBindingFn
prop function. We are going to check if we need to start a list here. If so, we need to return a so calledDraftEditorCommand
, which is a string. Also, to benefit from OS-level commands we need to add a getDefaultKeyBinding
function call as a fall-through case.
Draft.js在keyBindingFn
prop函數中為我們公開了一個keyDown
事件。 我們將檢查是否需要在此處開始列表。 如果是這樣,我們需要返回一個所謂的DraftEditorCommand
,它是一個字符串。 另外,要從操作系統級別的命令中受益,我們需要添加getDefaultKeyBinding
函數調用作為getDefaultKeyBinding
案例。
We need to check if the currently pressed key is a space
. If so we would run our checks against the history
array. We check if we have a suitable set of previously pressed keys — *
for an unordered list and 1.
for an ordered one. If we find a match, we return a command(string) to be processed later.
我們需要檢查當前按下的鍵是否為space
。 如果是這樣,我們將對history
數組進行檢查。 我們檢查是否有一組合適的先前按下的鍵- *
表示無序列表, 1.
.表示有序鍵。 如果找到匹配項,則返回一個命令(字符串),以便稍后處理。
Now we need to implement the handleKeyCommand
prop function and pass it to the editor. The logic is pretty simple. If we get one of our custom commands, we check if we should start a list on the current block. So here is a skeleton of the handleKeyCommand
function.
現在,我們需要實現handleKeyCommand
prop函數并將其傳遞給編輯器。 邏輯很簡單。 如果得到自定義命令之一,則檢查是否應在當前塊上啟動列表。 因此,這是handleKeyCommand
函數的框架。
To check if we are good to start a list, we check if the currently selected block satisfies all three of the following rules:
要檢查是否可以很好地啟動列表,請檢查當前選定的塊是否滿足以下所有三個規則:
The block type is
unstyled
塊類型是無
unstyled
The block has a
depth
of 0塊的
depth
為0the block has
*
or1.
as a text該塊具有
*
或1.
作為文本
Let’s wrap it up with the code:
讓我們用代碼包裝一下:
Now we’re able to catch the exact case where Draft.js needs to start a list! Now it’s a time to implement the startList
function.
現在,我們可以捕捉到Draft.js需要啟動列表的確切情況! 現在是時候實現startList
函數了。
First of all, we need to map our custom commands to a particular list style. This means we need to start an unordered list for the start-unoredered-list
command.
首先,我們需要將自定義命令映射到特定的列表樣式。 這意味著我們需要為start-unoredered-list
命令啟動一個無序列表。
We start an ordered list for the start-ordered-list
command. Next, we need to update the styling of the block to the selected type. To do it we would use the toggleBlockType
function of RichUtils
module, which comes as a part of Draft.js.
我們為start-ordered-list
命令啟動一個有序列表。 接下來,我們需要將塊的樣式更新為選定的類型。 為此,我們將使用RichUtils
模塊的toggleBlockType
函數,該函數是RichUtils
的一部分。
Next we need to replace the shortcut text we’ve entered with an empty string. To do it we need to call the replaceText
method of the Modifier
module. This method requires a selection range to determine what should be replaced. We need to get the selection out of the block and update it to have focusOffset
value equal to block length. This combination means we want to replace the whole text we’ve entered.
接下來,我們需要將輸入的快捷方式文本替換為空字符串。 為此,我們需要調用Modifier
模塊的replaceText
方法。 此方法需要一個選擇范圍來確定應替換的內容。 我們需要從塊中取出選擇并進行更新,以focusOffset
值等于塊長度。 這種組合意味著我們要替換輸入的整個文本。
Great! Now we need to update our local editor state with the new state we get from the startList
function. So let’s bring it all together!
大! 現在,我們需要使用從startList
函數獲得的新狀態來更新本地編輯器狀態。 因此,讓我們將它們放在一起!
OK! We’re almost done! But there is one more moment we need to handle. In some cases when one of our custom commands fire, we should not start a list based on the output of the shouldStartList
function. We need to process the insertion of the space manually.
好! 我們快完成了! 但是,我們還有另外一刻需要處理。 在某些情況下,當我們的自定義命令之一觸發時,我們不應基于shouldStartList
函數的輸出來啟動列表。 我們需要手動處理空間的插入。
For implementation details of the getSelectedBlock
method, check out my previous post on this Draft.js topic!
有關getSelectedBlock
方法的實現細節,請查看我以前關于此Draft.js主題的文章!
To do this we may want to use a method called insertText
of the Modifier
module. Obviously enough, it is used to build a new content state with the provided text inserted into it. As always, we need to provide the current content state, current selection state and the text we want to insert (a single space in our case).
為此,我們可能需要使用Modifier
模塊的一個名為insertText
的方法。 顯然,它用于通過插入所提供的文本來構建新的內容狀態。 與往常一樣,我們需要提供當前的內容狀態,當前的選擇狀態和我們要插入的文本(在本例中為單個空格)。
We need to add a call to this function to our handleKeyCommand
function. So here is the final version of it:
我們需要在handleKeyCommand
函數中添加對此函數的調用。 所以這是它的最終版本:
If you’ve read this post all the way through, you may also want to check out my previous post about Draft.js enchantment. You may want to apply it to your project as well.
如果您已經閱讀了所有文章,那么您可能還想看看我以前有關Draft.js附魔的文章。 您可能還希望將其應用于您的項目。
翻譯自: https://www.freecodecamp.org/news/how-to-create-ordered-and-unordered-lists-in-draft-js-with-a-shortcut-5de34a1a570f/
draft.js