React富文本编辑器开发(十二)插件

插件

您已经看到了如何覆盖 Slate 编辑器的行为。这些覆盖也可以打包成 “插件”,以便重用、测试和共享。这是 Slate 架构中最强大的方面之一。

插件简单地是一个接受 Editor 对象并在某种方式上增强它后返回它的函数。

例如,一个将图像节点标记为 “void” 的插件:

const withImages = editor => {const { isVoid } = editoreditor.isVoid = element => {return element.type === 'image' ? true : isVoid(element)}return editor
}

然后要使用插件,简单地:

import { createEditor } from 'slate'const editor = withImages(createEditor())

这种插件组合模型使得 Slate 极易扩展!

辅助函数

除了插件函数之外,您可能还想公开与您的插件一起使用的辅助函数。例如:

import { Editor, Element } from 'slate'const MyEditor = {...Editor,insertImage(editor, url) {const element = { type: 'image', url, children: [{ text: '' }] }Transforms.insertNodes(editor, element)},
}const MyElement = {...Element,isImageElement(value) {return Element.isElement(element) && element.type === 'image'},
}

然后您可以在任何地方使用 MyEditor 和 MyElement,并在一个地方访问到所有的辅助函数。

渲染

Slate 最棒的部分之一是它构建在 React 上,因此它可以完美地适应您现有的应用程序。它不会重新发明自己的视图层,您不必学习新的东西。它尽可能地保持与 React 的一致性。

为此,Slate 允许您控制自定义节点和属性在您的富文本领域中的渲染行为。

您可以通过向顶级 <Editable> 组件传递 "render props" 来定义这些行为。

例如,如果您想要渲染自定义元素组件,您可以传递 renderElement prop

import { createEditor } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'const MyEditor = () => {const [editor] = useState(() => withReact(createEditor()))const renderElement = useCallback(({ attributes, children, element }) => {switch (element.type) {case 'quote':return <blockquote {...attributes}>{children}</blockquote>case 'link':return (<a {...attributes} href={element.url}>{children}</a>)default:return <p {...attributes}>{children}</p>}}, [])return (<Slate editor={editor}><Editable renderElement={renderElement} /></Slate>)
}

请确保在自定义组件中混合使用 props.attributesrender props.children!这些 attributes 必须添加到组件内部的顶级 DOM 元素中,因为它们是 SlateDOM 帮助函数所必需的。而 children 则是文本内容和内联元素所持有的 "leaves"

您不必使用简单的 HTML 元素,您也可以使用自己的自定义 React 组件:

const renderElement = useCallback(props => {switch (props.element.type) {case 'quote':return <QuoteElement {...props} />case 'link':return <LinkElement {...props} />default:return <DefaultElement {...props} />}
}, [])

叶子

当渲染文本级别的格式时,字符被分组为每个具有相同格式(标记)的文本 "leaves"

要自定义每个叶子的渲染,您可以使用自定义 renderLeaf prop

const renderLeaf = useCallback(({ attributes, children, leaf }) => {return (<span{...attributes}style={{fontWeight: leaf.bold ? 'bold' : 'normal',fontStyle: leaf.italic ? 'italic' : 'normal',}}>{children}</span>)
}, [])

请注意,我们处理它的方式与 renderElement 稍有不同。由于文本格式化通常相对简单,我们选择放弃 switch 语句,而只是切换一些样式开关。(但是,如果您愿意,您也可以使用自定义组件!)

与 Element 渲染器一样,确保在叶子渲染器中混合使用 props.attributesrender props.children!这些 attributes 必须添加到组件内部的顶级 DOM 元素中,因为它们是 SlateDOM 帮助函数所必需的。而 children 则是 Slate 为您自动管理的文档的实际文本内容。

文本级别的格式化的一个缺点是您不能保证任何给定格式是 “连续的” —— 也就是说它会作为一个单独的叶子保留。这与叶子相关的限制类似于 DOM,其中这是无效的:

<em>t<strong>e</em>x</strong>t

上面示例中的元素未正确关闭,因此无效。相反,您应该按以下方式编写上面的 HTML:

<em>t</em><strong><em>e</em>x</strong>t

如果您还添加了另一个重叠的 <strike> 部分到该文本中,您可能不得不再次调整闭合标签。在 Slate 中渲染叶子是类似的——您不能保证即使一个单词具有一种格式,该叶子也是连续的,因为它取决于它与其他格式的重叠方式。

当然,这个叶子的东西听起来很复杂。但是,只要您将文本级别的格式化和元素级别的格式化用于其预期目的,就不必过多考虑它:

  • 文本属性用于非连续的、字符级别的格式化。
  • 元素属性用于文档中连续的、语义化的元素。

装饰

装饰是另一种文本级别的格式化。它们与普通的自定义属性类似,只是每个装饰应用于文档的一个 Range 范围,而不是与给定文本节点关联。

然而,装饰是在渲染时基于内容本身计算的。这对于动态格式化(如语法高亮或搜索关键字)非常有帮助,因为内容的更改(或一些外部数据)可能会改变格式化。

装饰与 Marks 不同之处在于它们不存储在编辑器状态中。

工具栏、菜单、覆盖等等!

除了控制 Slate 内部节点的渲染之外,您还可以使用 useSlate hook 从其他组件中检索当前编辑器上下文。

这样,其他组件就可以执行命令、查询编辑器状态或执行其他任何操作。

一个常见的用例是渲染一个工具栏,其中的格式按钮基于当前选择而高亮:

const MyEditor = () => {const [editor] = useState(() => withReact(createEditor()))return (<Slate editor={editor}><Toolbar /><Editable /></Slate>)
}const Toolbar = () => {const editor = useSlate()return (<div><Button active={isBoldActive(editor)}>B</Button><Button active={isItalicActive(editor)}>I</Button></div>)
}

因为 <Toolbar> 使用 useSlate hook 检索上下文,所以当编辑器更改时它会重新渲染,这样按钮的活动状态就保持同步。

编辑器样式

可以通过在 <Editable> 组件上使用 style prop 来为编辑器自定义样式。

const MyEditor = () => {const [editor] = useState(() => withReact(createEditor()))return (<Slate editor={editor}><Editable style={{ minHeight: '200px', backgroundColor: 'lime' }} /></Slate>)
}

也可以使用样式表和 className 来应用自定义样式。但是,Slate 使用内联样式为编辑器提供了一些默认样式。由于内联样式优先于样式表,您使用样式表提供的样式将不会覆盖默认样式。如果您尝试使用样式表,但规则没有生效,请执行以下操作之一:

使用 style prop 而不是样式表来提供您的样式,这样会覆盖默认的内联样式。
disableDefaultStyles prop 传递给 <Editable> 组件。
在样式表声明中使用 !important,使其覆盖内联样式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/728263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

根据标签出现的频次渲染不同大小的圆和文字,圆随机摆放且相互之间不重叠

效果图&#xff1a; 按每个标签出现的频次大小渲染出不同比例大小的圆&#xff0c;渲染的圆的宽度区间为 [40, 160] &#xff0c;其中的文字的大小区间为 [12, 30] &#xff0c;圆的位置随机摆放且不重叠。 根据已知条件可得出&#xff0c;标签中频次最高的对应圆的宽度(直径…

蓝桥杯(3.7)

P1102 A-B 数对 import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int c sc.nextInt();int[] res new int[n1];for(int i1;i<n;i)res[i] sc.nextInt();int sum 0;for(i…

golang服务控制之go-svc

文章目录 程序安全退出执行代码的基本:信号拦截执行代码的改进:信号拦截包装器实践捕获键盘输入示例代码go-svc介绍程序及服务的控制是指在计算机系统中对程序和服务进行管理、监控和调控的过程。这个过程可以涉及到多个方面,包括资源管理、运行状态监测、安全性控制等。本质…

ROS2学习(二):仿真案例汇总(基于Ubuntu_2004 ROS2_noetic)

文章目录 一、slam仿真1、安装环境依赖2、创建Turtlebot3目录并下载安装3、配置Turtlebot3环境4、运行slam仿真 一、slam仿真 1、安装环境依赖 sudo apt install ros-noetic-cartographer ros-noetic-cartographer-ros2、创建Turtlebot3目录并下载安装 mkdir -p catkin_turt…

Chrome浏览器好用的几个扩展程序

Chrome好用的扩展程序 背景目的介绍JsonHandle例子未完待续。。。。。。 背景 偶然在往上看到Chrome有很多好用的扩展程序&#xff0c;比较好用&#xff0c;因此记录下比较实用的扩展程序。 目的 记录Chrome浏览器好用的插件。 介绍 JsonHandle下载以及无法扩展插件的解决…

YOLOv5目标检测学习(2):运行一个yolo应用所需要配置的深度学习环境

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、CUDA、CUDNN的下载安装1.1 CUDA的安装1.2 cuDNN的配置 二、anaconda的安装1.卸载python2.安装anaconda 三、Pytorch、python虚拟环境安装1.创建虚拟环境2.安…

【算法训练营】:期末考试

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 如果需要答案代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 考题12-1 题目描述 输入格式 输出格式 输出到标准输出。 输出一行一个整数…

php 把数字转化为大写中文

1. 120002129.25 转化后壹億贰仟萬贰仟壹佰贰拾玖圆贰角伍分2. 12000.2145 转化后壹萬贰仟圆贰角壹分肆厘伍毫3. 1020001211 转化后壹拾億贰仟萬壹仟贰佰壹拾壹圆整大致思路这样的: 从小数点分割成两部分,整数部分和小数部分分别处理。 整数四个一组进行处理,用substr函数分…

蓝桥杯练习题-特殊日期

问题描述&#xff1a; 对于一个日期&#xff0c;我们可以计算出年份的各个数位上的数字之和&#xff0c;也可以分别计算月和日的各位数字之和。 请问1900年1月1日至9999年12月31日总共有多少天&#xff1f;年份的数位数字之和等于月的数位数字之和加日的数位之和 例如&#xff…

电销平台架构的演变与升级

简介 信也科技电销平台承载了公司400多坐席的日常外呼任务&#xff0c;随着公司业务规模不断增长&#xff0c;业务复杂度不断提升&#xff0c;营销模式需要多样化&#xff0c;营销流程需要更加灵活。为了更好地赋能业务、提高客户转化率&#xff0c;电销平台不断升级优化&#…

利用Spring整合Redis

文章目录 利用Spring整合Redis引入依赖配置Redis 访问RedisString类型数据Hash类型数据List类型数据Set类型数据SortedSort类型数据全局key简化多次访问同一个key情况代码 Redis中的事务核心方法execute()事务代码实例 参考文献 利用Spring整合Redis 引入依赖 spring-boot-st…

springboot快速构建项目

1.Spring的基本步骤 2.构建项目 第一次下包速度比较慢&#xff0c;可以考虑使用镜像 至此项目构建完成 3.启动并配置数据库 新建一个数据库&#xff0c;新建一个表 下面这里也可以【重构-重命名】为yml后缀&#xff08;代码可粘下面的&#xff0c;后面有写&#xff09; Yml后…

FreeRTOS_day2

作业&#xff1a;1.使用ADC采样光敏电阻数值&#xff0c;如何根据这个数值调节LED灯亮度。 2.总结DMA空闲中断接收数据的使用方法 打开DAM,允许接收外部设备数据&#xff0c;调用中断接收回调函数

Eclipse调试技巧 条件断点 监视

实验代码 import java.util.Scanner;public class Test {// 判断n是否为质数public static boolean isPrime(int n){if (n < 2)return false;for (int i 2; i < n; i){if (n % i 0)return false;}return true;}public static void main(String[] args){Scanner scanne…

前端每日一练:深入理解CSS浮动、问题及清除浮动解决方案

深入理解CSS浮动、问题及解决方案 在CSS布局中&#xff0c;浮动&#xff08;float&#xff09;是一种常见的布局属性&#xff0c;用于控制元素在其父元素中的位置&#xff0c;使其可以浮动到左侧或右侧。然而&#xff0c;浮动也会引起一些常见的问题&#xff0c;主要涉及到高度…

专治Java底子差,线程操作篇(1)

&#x1f497;推荐阅读文章&#x1f497; &#x1f338;JavaSE系列&#x1f338;&#x1f449;1️⃣《JavaSE系列教程》&#x1f33a;MySQL系列&#x1f33a;&#x1f449;2️⃣《MySQL系列教程》&#x1f340;JavaWeb系列&#x1f340;&#x1f449;3️⃣《JavaWeb系列教程》…

[网络安全] PKI

一、PKI 概述 名称; 公钥基础设施 (Public Key Facility) 作用: 通过加密技术和数字签名保证信息安全 组成: 公钥机密技术、数字证书、CA、RA 二、信息安全三要素 机密性&#xff1a;确保仅信息发收双方 能看懂信息 完整性&#xff1a; 确保信息发收完整&#xff0c;不被破坏 …

最新基于R语言lavaan结构方程模型(SEM)技术应用

结构方程模型&#xff08;Sructural Equation Modeling&#xff0c;SEM&#xff09;是分析系统内变量间的相互关系的利器&#xff0c;可通过图形化方式清晰展示系统中多变量因果关系网&#xff0c;具有强大的数据分析功能和广泛的适用性&#xff0c;是近年来生态、进化、环境、…

前端每日一练:如何隐藏一个元素​?

css 中隐藏元素的方法有很多&#xff0c;但他们也各有差异&#xff0c;不同场景选择合适的方式能事倍功半&#xff01; 方式​ 占位​ 点击事件​ display: none​ ❌​ ❌​ opacity: 0​ ✅​ ✅​ visibility: hidden​ ✅​ ❌​ clip-path: circle(0)​ ✅​…

支小蜜校园防欺凌系统如何有效应对学生霸凌?

学生霸凌不仅直接伤害到被霸凌者的身心健康&#xff0c;也对整个校园的和谐氛围构成了威胁。为了应对这一问题&#xff0c;校园防欺凌系统应运而生&#xff0c;成为维护校园安全、保护学生权益的重要工具。那么当校园防欺凌系统面对学生霸凌时&#xff0c;该如何有效应对呢&…