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的简单数组。 该数组将存储所按下键的值。 我们绝对不希望使用shiftalt等修饰符来处理任何按键。 我们可以使用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为0

  • the block has * or 1. 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

draft.js_如何使用快捷方式在Draft.js中创建有序列表和无序列表相关推荐

  1. js中创建form表单

    有的时候需要在js中创建form向controller提交数据,下面是在工作中遇到的一些问题和解决办法: 简单的用jquery创建form: var form = $("<form m ...

  2. ENSP如何开启服务器的http_如何使用HTTP模块在Node.js中创建Web服务器(上)

    当你在浏览器中查看网页时,其实是在向互联网上的另一台计算机发出请求,然后它会将网页提供给你作为响应.你通过互联网与之交谈的那台计算机就是Web服务器,Web服务器从客户端(例如你的浏览器)接收HTTP ...

  3. 【翻译】在Ext JS中创建特定主题的重写

    Ext JS提供了大量的功能来使类的创建和处理变得简单,还提供了一系列的功能来扩展和重新现有的Javascript类.这意味着可以为类添加行为和创建属于自己的类,或者重写某些函数的行为.在本文,将展示 ...

  4. react.js app_在React.JS中创建一个Weather App

    react.js app Hello readers! 各位读者好! In this article, you will know how to develop a basic weather app ...

  5. js中创建桌面网页快捷方式代码

    有些时候,我们编写软件需要创建桌面的快捷方式,有很多种方式实现,这里有我测试过已经实现的js代码,代码如下: function toDesktop(sUrl, sName) {             ...

  6. JS中创建函数的几种方式

    使用 "函数声明" 创建函数 语法:* function 函数名([形参1,形参2...形参N]){* 语句...* } */function fun2(){console.log ...

  7. spreadsheet js中创建下拉列表_JS 中创建自定义排序方法

    原文:https://www.youtube.com/watch?v=zVevl-K-m7Y 译者:前端小智 为了保证的可读性,本文采用意译而非直译. 想优质文章请猛戳GitHub博客,一年百来篇优质 ...

  8. JS 中 Object 的 keys 是无序的吗?

    在最开始学习 JavaScript 时,我一直被灌输 Object 中的 Key 是无序的,不可靠的,而与之相对的是 Map 实例会维护键值对的插入顺序. 「But,Object 的键值对真的是无序的 ...

  9. Node.js中创建package.json文件,安装第三方包

    在当前项目根目录下打开命令窗口 输入,开启安装向导 npm init 依次输入之后即可生成package.json文件,也可以不完全填写全部信息,不想填的回车可跳过. package name: (包 ...

最新文章

  1. python之路——模块和包
  2. java set null值,从Java ResultSet检查null int值
  3. oracle 分列,SQL 问题 如何分列
  4. Docker技术实践——中级篇
  5. 你有没有觉得邮件发送人固定配置在yml文件中是不妥当的呢?SpringBoot 动态设置邮件发送人
  6. 【远程操控】Pycharm远程连接服务器之本地显示独立的plot窗口
  7. 对话李飞飞,揭秘国际体育赛事风“云”背后的黑科技
  8. python所有实验_python列表的小实验
  9. 构建高性能ASP.NET站点 开篇
  10. css行内元素和块级元素
  11. java多态 重写(override)的调用优先级
  12. JSP中用request.setAttribute()后,在action中为什么取不到值?
  13. 讲座记录《捷联惯导解算的历史及发展》
  14. 肖哥所有课程/HCNA HCNP/安全/云计算/虚拟化/linux/视频教程/资料软件下载链接
  15. Frechlet Inception Distance(FID)快速入门、使用、代码
  16. python三国演义人物出场_Python教你查询《三国演义》书籍人物出场次序
  17. android开发教程 电驴资源下载地址分享
  18. java将bmp文件转为jpg_在PHP中将BMP转换为JPG
  19. 2022081班李亚楠20220926
  20. 字体的大小(pt)和像素(px)如何转换?

热门文章

  1. linux拉取指定时间内,Linux 日期和时间操作详解
  2. php智能裁剪黑边,图片裁剪去除黑边
  3. serial port 的操作
  4. redis的源码编译安装+发布订阅+RDB持久化
  5. Django之model补充:一对多、跨表操作
  6. python DB.fetchall()--获取数据库所有记录列表
  7. easybcd 支持 windows 10 和 ubuntu 14.04 双系统启动
  8. [转]项目失败的经验
  9. 基于easyui开发Web版Activiti流程定制器详解(三)——页面结构(上)
  10. 本文将引导你使用XNA Game Studio Express一步一步地创建一个简单的游戏