React富文本编辑器开发(三)

news2024/9/17 8:30:54

现在我们的编辑器显示的内容很单一,这自然不是我们的目标,让呈现的内容多元化是我们的追求。这就需要让编辑器能够接收多元素的定义。从初始数据的定义我们可以推断数据的格式远不止一种,那么其它类型的数据如何定义及呈现的呢,我们新建一个文件elements.jsx,创建一个元素组件:

_elements.jsx

export const CodeElement = props => {
    return (
        <pre {...props.attributes}>
            <code>{props.children}</code>
        </pre>
    )
}

这个组件平常的不能再平常了。就是一个 <pre/>元素。当然我们还要添加一个默认的渲染元素,如下所示:

export const DefaultElement = props => {
  return <p {...props.attributes}>{props.children}</p>
}

我们要让这个元素和数据对应起来,修改configure.jsx中的初始化值,添加如下内容:

_configure.jsx

export const initialValue = [
    {
        type: 'paragraph',
        children: [{ text: '这是一行段落文字,内容很少,但很重要!!' }],
    },

    {
        type: 'code',
        children: [{ text: '这是一代码行段落文字,内容很少,但很重要!!' }],
    },
];

我们增加一个code数据段。接下来要做的就是我们要设置一个渲染器, 根据数据类型的不同渲染不同的元素:

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

当然还要把这个渲染器指定给 EditablerenderElement属性:

<Editable
  renderElement={renderElement}
  onKeyDown={event => {
    if (event.key === '&') {
      event.preventDefault()
      editor.insertText('and')
    }
  }}
/>

完整的代码如下:

SDocer.jsx

import { useState } from 'react';
import { createEditor } from 'slate';
import { Slate, withReact, Editable } from 'slate-react';

import { initialValue } from './_configure';
import { CodeElement, DefaultElement } from './_elements';

function SDocer() {
  const [editor] = useState(() => withReact(createEditor()));

  const renderElement = useCallback(props => {
    switch (props.element.type) {
      case 'code':
        return <CodeElement {...props} />
      default:
        return <DefaultElement {...props} />
    }
  }, []);

  return (
    <Slate editor={editor} initialValue={initialValue}>
      <Editable
        renderElement={renderElement}
        onKeyDown={event => {
          if (event.key === '&') {
            event.preventDefault()
            editor.insertText('and')
          }
        }}
      />
    </Slate>
  )
}

export default SDocer;

效果如下:
在这里插入图片描述

现在新的要求来了,我们希望能动态的把选中的段落转换化<pre>元素,相反也能转化回默认元素。为了让两者的元素有较大的变化,我们对CodeElement元素组件加个样式,看下面的代码:

export const CodeElement = props => {
    return (
        <pre
            {...props.attributes}
            style={{
                fontSize: "20px",
                lineHeight: 2,
            }}
        >
    <code>{props.children}</code>
        </pre >
    )
}

然后对 SDocer修改如下:

import { useState, useCallback} from 'react';
import { createEditor, Editor, Transforms, Element } from 'slate';
import { Slate, withReact, Editable } from 'slate-react';

import { initialValue } from './_configure';
import { CodeElement, DefaultElement } from './_elements';

function SDocer() {
  const [editor] = useState(() => withReact(createEditor()));

  const renderElement = useCallback(props => {
    switch (props.element.type) {
      case 'code':
        return <CodeElement {...props} />
      default:
        return <DefaultElement {...props} />
    }
  }, []);

  return (
    <Slate editor={editor} initialValue={initialValue}>
      <Editable
        renderElement={renderElement}
        onKeyDown={event => {
          if (!event.ctrlKey) return;
          
          if (event.key === '`') {
            event.preventDefault()

            const [match] = Editor.nodes(editor, {
              match: n => n.type === 'code',
            })

            Transforms.setNodes(
              editor,
              { type: match ? 'paragraph' : 'code' },
              { match: n => Element.isElement(n) && Editor.isBlock(editor, n) }
            )
          }
        }}
      />
    </Slate>
  )
}

export default SDocer;

这样,如果您按 Ctrl + ' 时光标所在的块应该会变成一个代码块。再次按一次时就变成普通的文本段落。如下所示:

在这里插入图片描述

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

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

相关文章

【 C++ 】智能指针

1、内存泄漏 什么是内存泄漏&#xff0c;内存泄漏的危害 什么是内存泄漏&#xff1a; 内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失&#xff0c;而是应用程序分配某段内存后&#xff0c;因为设计错误&#xff0c…

操作系统导论

操作系统的概念&#xff1a; 操作系统是管理计算机硬件的程序&#xff0c;它还为应用程序提供基础&#xff0c;并且充当计算机硬件和计算机用户之间的中介。 操作系统做什么&#xff1a; 计算机系统可以大致分为四个部分&#xff1a;硬件&#xff0c;操作系统&#xff0c;系…

kafka查看数据_Kafka 数据积压情况查看

由于消息消费速度处理慢或是消费端故障会导致数据产生积压。 那怎么查看数据积压量呢&#xff1f; Consumer-Groups管理&#xff1b; 在Kafka 的bin目录下提供了 kafka-consumer-groups.sh 脚本。此脚本用于管理消费情况。 查询消费者组 $KAFKA_DIR/bin/kafka-consumer-groups…

【Sql server】假设有三个字段a,b,c 以a和b分组,如何查询a和b唯一,但是c不同的记录

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

深入理解计算机系统笔记

1.1 嵌套的数组 当我们创建数组的数组时&#xff0c;数组分配和引用的一般原则也是成立的。 例如&#xff0c;声明 int A[5][3]; 等价于下面的声明 typedef int row3_t[3]; row3_t A[5] 要访问多维数组的元素&#xff0c;编译器会以数组起始为基地址&#xff0c; (可能需…

教你快速认识Java中的继承和多态

目录 继承 继承的概念 继承的语法 父类成员访问 在子类方法中或者通过子类对象访问父类成员变量时&#xff1a; 在子类方法中或者通过子类对象访问父类成员方法时&#xff1a; super关键字 子类构造方法&#xff1a; 代码块执行顺序: 多态 多态的实现条件 重写 重…

MySql安全加固:配置不同用户不同账号禁止使用旧密码禁止MySql进程管理员权限

MySql安全加固&#xff1a;配置不同用户不同账号&禁止使用旧密码&禁止MySql进程管理员权限 1.1 检查是否配置不同用户不同账号1.2 检查是否禁止使用旧密码1.3 禁止MySql进程管理员权限 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496…

shell自定义日志输出函数log

Background 在编写比较复杂的脚本时&#xff0c;需要输出相关日志信息&#xff0c;方便知悉脚本的执行情况以及问题的排查。 源码 log.sh # 自定义日志函数 function log(){if [[ $1 "i" || $1 "info" ]]; thenecho -ne "\033[1;34mINFO: \033[0m&…

使用Python操作SQLite数据库

大家好&#xff0c;在数据涌现的今天&#xff0c;数据库已成为生活中不可或缺的工具。Python作为一种流行的编程语言&#xff0c;内置了多种用于操作数据库的库&#xff0c;其中之一就是SQLite。SQLite是一种轻量级的关系型数据库管理系统&#xff0c;它在Python中的应用非常广…

c++异常机制(6) -- 标准库中的异常类

标准程序库异常 我们使用c标准库中的异常类&#xff0c;来实现我们之前文件拷贝的代码。 #include <iostream> #include <stdlib.h> #include <exception> #include <ios>using namespace std;#define BUFFER_SIZE 1024// 将一个文件中的内容拷贝到另…

python中版本,操作系统等问题汇总

1. linux源码部署到windows 1.1ModuleNotFoundError: No module named pwd 这个问题&#xff0c;是因为源码是给linux的。这里在windows中&#xff0c;没有该命令。 解决方法之一&#xff0c;在相应的环境目录中&#xff0c;如图中<MetaGPTenv>虚拟环境中&#xff0c;在…

makefileGDB使用

一、makefile 1、make && makefile makefile带来的好处就是——自动化编译&#xff0c;一旦写好&#xff0c;只需要一个make命令&#xff0c;整个工程完全自动编译&#xff0c;极大的提高了软件开发的效率 下面我们通过如下示例来进一步体会它们的作用&#xff1a; ①…

今日arXiv最热大模型论文:点击即可播放!港中文发布大模型写歌神器!

一首歌&#xff0c;包含作词作曲两个部分。擅长作词or作曲就已经很牛了。比如方文山是周杰伦的御用作词人&#xff0c;而周杰伦写过很多耳熟能详的曲子。而兼具作词作曲才华的全能创作人却是难得一见。 最近港中文发布了一款歌曲创作大模型SongComposer&#xff0c;作词作曲都…

Pegasus智能家居套件样例开发--软定时器

样例简介 此样例将演示如何在Pegasus Wi-Fi IoT智能家居套件上使用cmsis 2.0 接口进行定时器开发。 工程版本 系统版本/API版本&#xff1a;OpenHarmony 3.0 releaseIDE版本&#xff1a;DevEco Device Tool Release 3.0.0.401 快速上手 准备硬件环境 预装windows系统的PC…

uniapp项目申请短信模板临时Nginx配置

现在申请短信模板不允许有变量&#xff0c;且要指向实际业务网站&#xff0c;因为项目是小程序&#xff0c;用uniapp写的&#xff0c;现在申请短信&#xff0c;把uniapp打包成h5项目&#xff0c;上传至服务器&#xff0c;修改niginx配置中springboot项目部分&#xff0c;记录一…

Netty之ChannelHandlerMask详解

Netty的ChannelHandlerMask是用于标记ChannelHandler的位掩码。它被用于指示ChannelHandler的事件处理方式。ChannelHandlerMask 定义了ChannelHandler所有事件。 final class ChannelHandlerMask {static final int MASK_EXCEPTION_CAUGHT 1;static final int MASK_CHANNEL_…

前端src中图片img标签资源的几种写法?

在 Vue 项目中引用图片路径有几种不同的方法&#xff0c;具体取决于你的项目结构和配置。以下是几种常见的方式&#xff1a; 1. 静态资源目录 (Public) 如果你的图片放在了项目的 public 目录下&#xff08;例如&#xff0c;Vite 和 Create Vue App 脚手架工具通常使用这个目…

关于页面置换算法的例题(2)

考虑一个500字的程序的下述逻辑地址访问序列&#xff1a;10&#xff0c;11&#xff0c;104&#xff0c;170&#xff0c;73&#xff0c;309&#xff0c;185&#xff0c;245&#xff0c;246&#xff0c;434&#xff0c;458&#xff0c;364。假定采用页式虚拟内存管理&#xff0c;…

力扣hot100题解(python版41-43题)

41、二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…

理解C#里面的集合有哪些?怎么用,什么是安全集合?

介绍 在C#中&#xff0c;集合是一种用于存储和操作多个元素的数据结构。它们提供了各种操作&#xff0c;如添加、删除、查找等&#xff0c;以及遍历集合中的元素。集合通常根据其实现方式和行为特征进行分类。 集合继承IEnumerable 在C#中&#xff0c;几乎所有的集合类型都实现…