广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Rust+React创建富文本编辑器
  • 651
分享到

Rust+React创建富文本编辑器

2024-04-02 19:04:59 651人浏览 薄情痞子
摘要

目录简介数据模型核心逻辑视图手动差异化杂项总结简介 在Fiberplane,我们最近遇到了一个有趣的挑战:我们正在使用的富文本编辑器库已经过时了。我们曾经使用Slate.js&mda

简介

在Fiberplane,我们最近遇到了一个有趣的挑战:我们正在使用的富文本编辑器库已经过时了。我们曾经使用Slate.js——一个很好的编辑器——但是当我们为协作编辑实现我们自己的富文本基元时,我们发现我们自己的基元和Slate的数据模型之间的脱节是一个阻碍因素。所以我们开始思考——如果我们建立自己的富文本编辑器(RTE, Rich Text Editor)会怎样?

从一个非常高层次的角度来看,一个富文本编辑器是由两个部分组成的。

  • 一个数据模型和对其进行操作的核心逻辑。
  • 一个渲染上述数据模型的状态并处理用户互动的视图。

我们在视图中使用了Slate,但结果是它也拉入了自己的数据模型。如果我们可以直接在React中实现视图,我们可以大大简化我们的堆栈,并完全控制它的每个方面。缺点是什么?RTEs因为需要支持复杂的用户交互而臭名昭著,而现在我们需要自己处理每一个交互。

在这篇文章中,我们将讨论我们所面临的挑战以及我们如何解决这些问题。

数据模型

我们的产品是一个协作式的笔记本编辑器。笔记本是一个基于块的编辑器,由不同类型的单元组成,从文本单元到图片和图表。因此,我们确定了一个数据模型,它既有利于我们的协作功能,也有利于为我们在单元格内使用的任何富文本字段提供动力的RTE。在这篇文章中,我们将重点讨论TextCell

struct TextCell {
    pub id: String,
    pub content: String,
    pub fORMatting: Option<Formatting>,
}

这里的content只是纯文本内容,而formatting是将纯文本变成富文本的东西。"多汁"的部分都在格式化类型里面。

type Formatting = Vec<AnnotationWithOffset>;
​
struct AnnotationWithOffset {
    annotation: Annotation,
    offset: u32,
}
​
enum Annotation {
    StartBold,
    EndBold,
    StartItalics,
    EndItalics,
    StartLink { url: String },
    EndLink,
    
}

正如你所看到的,这只不过是一个注释列表,它定义了要应用的格式化类型和它开始的偏移量。我们有意不选择类似于html的树状结构,因为格式化范围可以重叠,这将导致复杂的树状操作。此外,每个注释只有一个偏移量的简单性使我们很容易实现我们用于协作的操作转换(OT)算法

核心逻辑

随着数据模型的出现,也带来了与之互动的代码。当你在一个单元格中打字时,我们在哪里插入新打的字符?这如何影响content和相关的formatting?如果你在一个选择上切换格式,应该发生什么?如果你将一个单元格从中间分割开来,又该怎么办?所有这些以及更多都在Rust的核心逻辑中实现。

你要知道,无论如何我们都需要这些逻辑,因为我们的OT算法也需要它。但现在我们也能用同样的原语来驱动我们的编辑器。

为了使这个逻辑易于测试,它被实现为纯函数,我们在typescript的Redux reducer中调用。我们创建了fp-bindgen来生成Rust代码和调用它的TypeScript代码之间的绑定关系。

为了适应RTE(当我们还在使用Slate时还不需要),我们不得不自己引入一段逻辑,就是光标管理。例如,当用户按下左方向键时,我们分派一个MoveCursor动作,其有效载荷如下。

struct MoveCursorPayload {
    pub delta: i32,
    pub extend_selection: bool,
    pub unit: CursorUnit,
}

delta指定光标是向前还是向后移动,通过指定一个1-1的值。extend_selection属性是在用户按住Shift键时使用的,用来扩展当前的选择,或者在还没有选择的情况下创建一个。这个unit决定了我们是按Unicode字母群(用户通常称之为 "字符")还是按单词移动光标,用于用户按住Ctrl/键时。然后,我们的Rust还原器会处理这些动作,并处理所有的边缘情况,包括确保光标不会出现在@的中间。

视图

在我们RTE的大部分开发过程中,我们的编辑器甚至不是一个编辑器。至少从浏览器的角度来看不是。这是因为浏览器通常只识别两种类型的编辑器:纯文本编辑器,如<input><textarea>元素,以及使用一种叫做contenteditable的属性创建的自由格式编辑器。我们的编辑器两者都不是。

我们在最终版本中仍然使用contenteditable属性,因为我们很快会讨论一些实际的影响,但我们有意识地决定尽可能少地依赖它。这对我们最初构建RTE的方式产生了深远的影响,你将在本节中看到。

如果我们最初的版本根本没有使用contenteditable,那么我们怎么能够创建一个富文本编辑器?从用户的角度来看,RTE只不过是一个看起来像文本字段的东西,有一个光标,允许他们输入任何他们喜欢的内容。

所以我们创建了一个普通的React组件,并根据单元格的contentformatting生成了富文本内容,然后使用React.createElement()插入实际的元素,这些元素只是一个应用了样式的<span>元素的平面列表(偶尔会有<a>元素洒在链接上)。然后,我们添加了必要的事件处理程序来捕捉用户的互动,这又将再次调用数据模型上的适当逻辑。

那么用户的光标呢?只是另一个我们自己插入的小React组件。我们会在useLayoutEffect()钩子中测量它需要的位置,然后根据这个来定位它。

所以......很简单,很容易,对吗?好吧,我们现在需要处理的大量的交互使这成为一个重大的挑战。例如,让我们再看一下光标导航。上一节中的例子显示了如何向左和向右移动光标。但是如果用户按了向下的箭头,他们的光标最终会在哪两个字符之间呢?这不是一个简单的问题,因为保持光标的垂直位置需要测量上面那一行的字符的位置。但你如何定义什么是 "上面那一行"?无论是content还是formatting都不包含这些信息。然后记住我们还必须支持选择。还有鼠标互动...

这当然会让人感到不知所措,在开发过程中,可能很难保持对哪些工作和哪些不工作的概述。而这正是我们觉得最初没有contenteditable的工作很好的原因。我们自己做所有的事情,使我们非常清楚自己的位置。任何不工作的交互都是我们仍然需要实现的。没有什么会意外地工作,因为浏览器为我们解决了这个问题--浏览器在这里处于次要地位。

当然,对于最终的版本,很难绕过使用contenteditable。这是因为如果没有它,浏览器扩展将无法识别你的编辑器。而移动浏览器甚至会顽固地拒绝调出屏幕键盘......

手动差异化

所以我们确实需要contenteditable,但是还有一个问题。React不支持对已启用contenteditable的元素的内容进行修补。这是有原因的:contenteditable基本上是告诉浏览器去玩吧。这就像一个没有规则的操场。

React并不喜欢这样。它依靠虚拟DOM来决定它需要如何更新实际的DOM,但当浏览器可以在它不知情的情况下把地毯从它下面拉出来并更新实际的DOM时,这种方法就陷入了困境。这也是我们一开始就避免的原因。为了在更新我们的数据模型时能够保留用户的意图(OT算法的一个重要方面),最好是了解导致任何变化的互动。但是,如果你试图理解浏览器对DOM在内容可编辑元素中的变化,你最多只能是猜测。

所以我们借鉴了React的玩法,实现我们自己的差异算法。但我们不是针对虚拟DOM进行差分,而是在useLayoutEffect()钩子函数中针对真实DOM进行差分和修补。这相对简单,因为我们的用例非常专业,而且它还有一个好处,如果真实DOM中发生任何意外(可能是由于浏览器扩展),我们的算法将简单地将视图恢复到我们基于数据模型的预期。

杂项

上述所有内容可能会让你对编辑器的工作原理有一个较高的认识,但魔鬼是在细节中的。下面是我们需要解决的一些小问题。

  • 支持Unicode。每个人都喜欢的标准,但在工作中却很麻烦。幸运的是,Rust有优秀的unicode_segmentation板块,对我们帮助很大。这帮助我们解决了一些问题,比如按字进行光标导航,以及确保光标能正确地跳过字母群。
  • 光标定位是很棘手的,但我们发现最好的方法是使用浏览器的Selection对象,并通过这种方式设置一个(透明的)本地光标。然后我们使用getBoundinGClientRect()来测量浏览器渲染光标的位置,然后我们就可以在那里定位我们自己的光标。
  • 组合事件被浏览器用来组成带有重音的字符和处理拼音等输入。不要忘记处理这些。

总结

创建你自己的富文本编辑器是一项艰巨的任务,但只要有正确的架构和良好的规划,它肯定是可以做到的。如果你发现自己处于必须选择或开发一个富文本编辑器的位置,我们希望你能发现这篇文章的有用信息。

注:特别感谢技术指导dazhao(赵达)对本文翻译的审阅指正。

作者:Arend van Beelen

原文链接:Creating a Rich Text Editor using Rust and React

以上就是Rust+React创建富文本编辑器的详细内容,更多关于Rust React富文本编辑器的资料请关注编程网其它相关文章!

--结束END--

本文标题: Rust+React创建富文本编辑器

本文链接: https://www.lsjlt.com/news/153420.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Rust+React创建富文本编辑器
    目录简介数据模型核心逻辑视图手动差异化杂项总结简介 在Fiberplane,我们最近遇到了一个有趣的挑战:我们正在使用的富文本编辑器库已经过时了。我们曾经使用Slate.js&mda...
    99+
    2022-11-13
  • 怎么使用Rust+React创建富文本编辑器
    这篇文章主要介绍“怎么使用Rust+React创建富文本编辑器”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用Rust+React创建富文本编辑器”文章能帮助大家解决问题。数据模型我们的产品是...
    99+
    2023-07-02
  • JavaScript如何实现富文本编辑器
    这篇文章主要介绍JavaScript如何实现富文本编辑器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前段时间在寻找一些关于富文本编辑器的资料,然后发现了这个名为 Pell 的项目,...
    99+
    2022-10-19
  • JavaScript中怎么实现富文本编辑器
    JavaScript中怎么实现富文本编辑器,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Document.execCommand()先从最简单...
    99+
    2022-10-19
  • Html5富文本编辑器的示例分析
    这篇文章给大家分享的是有关Html5富文本编辑器的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 使用H5的全局属性contentedita...
    99+
    2022-10-19
  • Vue怎么整合富文本编辑器TinyMce
    本篇内容主要讲解“Vue怎么整合富文本编辑器TinyMce”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue怎么整合富文本编辑器TinyMce”吧!选择一个合适的富文本编辑器对于一个前端项目至...
    99+
    2023-07-04
  • Vue2.0中如何集成UEditor富文本编辑器
    小编给大家分享一下Vue2.0中如何集成UEditor富文本编辑器,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!首先,去官网上下...
    99+
    2022-10-19
  • Vue中如何使用tiptap富文本编辑器
    Vue中如何使用tiptap富文本编辑器,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。为什么使用tiptap?市面上有不少富文...
    99+
    2022-10-19
  • Vue+Webpack如何整合富文本编辑器TinyMce
    这篇文章主要为大家展示了“Vue+Webpack如何整合富文本编辑器TinyMce”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Vue+Webpack如何整合富...
    99+
    2022-10-19
  • Vue.js中如何使用Ueditor富文本编辑器
    这篇文章将为大家详细讲解有关Vue.js中如何使用Ueditor富文本编辑器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. 总体思路1.1 模块化vue...
    99+
    2022-10-19
  • ASP.NET MVC如何实现layui富文本编辑器
    这篇“ASP.NET MVC如何实现layui富文本编辑器”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一...
    99+
    2022-10-19
  • JS中富文本编辑器TinyMCE的示例分析
    小编给大家分享一下JS中富文本编辑器TinyMCE的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、题外话最近负责了一...
    99+
    2022-10-19
  • jquery如何获取富文本编辑器的内容
    在jquery中获取富文本编辑器内容的方法:1.新建html项目,引入jquery;2.使用UE.getEditor方法创建富文本编辑器;3.初始化编辑器;4.使用hasContents()方法判断内容;5.使用getContent()方法...
    99+
    2022-10-07
  • jquery怎么获取富文本编辑器的内容
    今天小编给大家分享一下jquery怎么获取富文本编辑器的内容的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。具体步骤如下:首先...
    99+
    2023-06-05
  • Ueditor 富文本编辑器 插入 m3u8 和 mp4 视频(PHP)
    当前环境:PHP、Ueditor的版本是1.4.3 新的需求是,需要在Ueditor 富文本编辑器中,插入视频播放,并且视频格式有MP4,也有M3U8。 百度编辑器默认的是embed,需要修改下配置。...
    99+
    2023-09-12
    音视频 php javascript Ueditor m3u8
  • node使用UEditor富文本编辑器的方法实例
    大部分编辑器的后台是基于java、php、asp等,很少有基于node.js的。今天就做一个基于node的 最近在做一个微信素材编辑器的小项目,使用到了UEditor编辑器,使用中出现了许多问题。 1.介绍...
    99+
    2022-06-04
    编辑器 实例 文本
  • nodejs后台集成ueditor富文本编辑器的实例
    UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.. 1 下载ueditor nodejs版本 2 ...
    99+
    2022-06-04
    编辑器 后台 实例
  • django轻松使用富文本编辑器CKEditor的方法
    前言 django是一个容易快速上手的web框架,用它来创建内容驱动型的网站(比如独立博客)十分方便。遗憾的是,django并没有提供官方的富文本编辑器,而后者恰好是内容型网站后台管理中不可或缺的控件。ck...
    99+
    2022-06-04
    编辑器 文本 轻松
  • vue-quill-editor+plupload富文本编辑器的示例分析
    这篇文章主要介绍vue-quill-editor+plupload富文本编辑器的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1,先给vue项目中下载vue-quill-ed...
    99+
    2022-10-19
  • vue2.x如何集成百度UEditor富文本编辑器
    小编给大家分享一下vue2.x如何集成百度UEditor富文本编辑器,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.首先下载U...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作