draft.js 粘贴文件
by Andrey Semin
通过安德烈·塞米(Andrey Semin)
For some of you this may be a surprise, but Draft.js doesn’t support images out of the box. To be able to display images in the Editor, you need to install and configure draft-js-image-plugin
(we won’t cover this topic here as its docs are pretty comprehensive). This also means there is no support for such a common feature like pasting images (or any other file) into the Editor. The goal of this post is to show how you can add basic support for pasting files (we will focus on images).
对于您中的某些人来说,这可能是一个惊喜,但是Draft.js不支持开箱即用的图像。 为了能够在编辑器中显示图像,您需要安装和配置draft-js-image-plugin
(我们不会在此讨论此主题,因为其文档非常全面)。 这也意味着不支持诸如将图像(或任何其他文件)粘贴到编辑器之类的通用功能。 这篇文章的目的是展示如何添加对粘贴文件的基本支持(我们将专注于图像)。
Let’s start by reading the Draft.js docs. It turns out there is a prop called handlePastedFiles
in the Editor. It receives an array of files and is supposed to provide you the option to manipulate with files on a paste action. However, things don’t work exactly this way.
让我们开始阅读Draft.js docs 。 事实证明,编辑器中有一个名为handlePastedFiles
的道具。 它接收文件数组,并应为您提供在粘贴操作中处理文件的选项。 但是,事情并非完全以这种方式工作。
There is an issue: when you try to paste multiple files into the Editor you will receive an array containing only one of them. This is a known problem and there was an issue opened in the Draft.js repo on 11 of December 2018. Which means it’s pretty young but still annoying.
有一个问题:当您尝试将多个文件粘贴到编辑器中时,您将收到一个仅包含其中一个的数组。 这是一个已知问题,并且于2018年12月11日在Draft.js存储库中打开了一个问题 。这意味着它还很年轻,但仍很烦人。
Now we need to define which file types we’re going to handle. For images, those are image/png
, image/jpeg
and image/gif
.
现在,我们需要定义要处理的文件类型。 对于图像,它们是image/png
, image/jpeg
和image/gif
。
Now when we know we are going to work only with images, it is time to actually read the data from the file. To do this we will implement a function called readImageAsDataUrl
and use the FileReader
API and readAsDataUrl
methods in particular. This combination of steps allows us to read the file and its content in base64 encoding which later can be used as a value of the src
attribute of the img
element.
现在,当我们知道我们将仅处理图像时,是时候实际从文件中读取数据了。 为此,我们将实现一个名为readImageAsDataUrl
的函数,并特别使用FileReader
API和readAsDataUrl
方法。 这些步骤的组合使我们能够以base64编码读取文件及其内容,以后可将其用作img
元素的src
属性的值。
Now when we have our base64 encoded image, all we need to do is to create a Draft.js entity and update the Editor’s state to contain this entity.
现在,当我们有了base64编码的图像时,我们所需要做的就是创建一个Draft.js实体,并更新编辑器的状态以包含该实体。
We can start by using the create
method of the Entity
module that is a part of Draft.js. (Keep in mind, though, that the documentation states Entity.create
is deprecated and developers should use contentState.createEntity
. The last one was not working at the time this post was written. So we’ll proceed with the usage of Entity
but will keep track of this change).
我们可以从使用Draft.js的Entity
模块的create
方法开始。 (不过请记住,该文档指出Entity.create
已过时,开发人员应使用contentState.createEntity
。在撰写本文时,最后一个不起作用。因此,我们将继续使用Entity
但会跟踪此更改)。
We need to provide 3 arguments here:
我们需要在此处提供3个参数:
the first is the type of entity we’re about to create (image
in our case)
首先是我们即将实体的类型来创建( image
在我们的例子)
the second is the mutability of the entity (IMMUTABLE
means we can’t edit the content of the text containing this entity. If we try to remove something from it, the whole text range would be removed)
第二个是实体的可变性( IMMUTABLE
表示我们无法编辑包含该实体的文本的内容。如果尝试从其中删除某些内容,则整个文本范围都将被删除)
and the third is an optional object containing any data you want to store with an entity (in our case it is src
which is required by draft-js-image-plugin
).
第三个是一个可选对象,其中包含要与实体存储的任何数据(在我们的示例中是src
,这是draft-js-image-plugin
所必需的)。
In return we get a key by which we can address this entity in the Editor state. Now we need to use this key to insert a block into the editor and attach this exact entity to this block. We will use the insertAtomicBlock
function of the AtomicBlockUtils
module from Draft.js. We need to pass the current Editor state, entity key, and a character (that should not be empty string — that’s why we use single space) and we will get a new Editor state!
作为回报,我们得到一个密钥,通过它我们可以在编辑器状态下寻址该实体。 现在,我们需要使用此键将一个块插入编辑器,并将这个确切的实体附加到该块。 我们将使用AtomicBlockUtils
模块的insertAtomicBlock
函数。 我们需要传递当前的Editor状态,实体键和一个字符(不应为空字符串-这就是我们使用单个空格的原因),我们将获得一个新的Editor状态!
Now when all is set let’s combine everything together and take a look at our handlePastedFiles
function:
现在,当所有设置完成后,让我们将所有内容组合在一起,看看我们的handlePastedFiles
函数:
Voilà! Now we can paste the image into Draft.js editor by simply pressing CTRL+V. You can extend this functionality in any way we want! For example we can allow our users to change the size of the images with some fancy UI.
瞧! 现在,只需按CTRL + V,就可以将图像粘贴到Draft.js编辑器中。 您可以按照我们想要的任何方式扩展此功能! 例如,我们可以允许用户使用一些精美的UI来更改图像的大小。
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附魔的文章。 您可能还希望将其应用于您的项目。
draft.js 粘贴文件