嗯?绝不允许你还没有属于自己的富文本编辑器
2023-10-16
1084 字约 4 分钟
...作为一名新时代农民工,几乎每个人都有自己的博客站点,而博客最重要的功能就是文档编辑,实现文档编辑无外乎Markdown、富文本编辑器两种模式。其中富文本编辑器使用起来比较简单,不需要额外了解各种语法,对非技术人员来说容易上手,本文就着重介绍一下富文本编辑器框架————Slate,它不仅可以帮助我们自定义实现富文本效果,而且还能实现类似于Markdown一样的语法输入。
说起Slate,可能很多人不了解,但是说起前端富文本插件库
wangEditor以及飞书文档,大家就不陌生了,这两款产品底层技术采用的就是Slate。
安装
Slate 本身是支持各种框架的,但是官方提供了React版本的库实现,我们就以React版本示例:
npm install slate slate-react
初始化编辑器
初始化编辑节点,并赋予编辑器默认内容。
注意默认内容的数据结构需要符合Slate的格式,其基本元素类型类似于HTML,包括块节点(Blocks)、行内节点(inlines)。可以通过
type字段区分不同的元素,后续我们的自定义节点就可以通过该字段区分。
// index.js
import { useState } from "react";
import { createEditor } from "slate";
import { Slate, Editable, withReact } from "slate-react";
import './index.css'
const SlateBox = ( ) => {
const [editor] = useState(() => withReact(createEditor()))
const [editorText, setEditorText] = useState([
{
type: 'paragraph',
children: [{
text: '这是一个slate内容的结构示例,每一段都是通过文本节点或者自定义节点的数组组成,文本节点必须包含text属性。' }]
}
])
return (
<Slate editor={editor} initialValue={editorText}>
<Editable className="editor-container" />
</Slate>
)
}
export default SlateBox;
优化编辑器样式:
/* index.css */
*{
box-sizing: border-box;
}
.editor-container{
width: 100vw;
height: 100vh;
padding: 8px;
background: #000;
color: #fff;
}
目前的效果图:
添加工具栏
富文本编辑器就是通过各种快捷按钮实现文本的不同效果,因此我们在编辑器顶部添加一个工具栏,展示一个高亮块按钮。
js
复制代码
`// index.js import { useState } from "react"; import { createEditor } from "slate"; import { Slate, Editable, withReact } from "slate-react"; import { Button } from 'antd' import { BulbOutlined } from '@ant-design/icons' import './index.css' const SlateBox = ( ) => { const [editor] = useState(() => withReact(createEditor())) const [editorText, setEditorText] = useState([ { type: 'paragraph', children: [{ text: '这是一个slate内容的结构示例,每一段都是通过文本节点或者自定义节点的数组组成,文本节点必须包含text属性。' }] } ]) const addHighBlock = ( ) => { console.log('添加高亮块') } return ( <Slate editor={editor} initialValue={editorText}> <div className="editor-toolbar"> <Button icon={<BulbOutlined />} className="menu-btn" type="text" onClick={addHighBlock}></Button> </div> <Editable className="editor-container" /> </Slate> ) } export default SlateBox;`
实现工具栏样式:
css
复制代码
`/* index.css */ *{ box-sizing: border-box; } .editor-toolbar{ background: #242426; height: 40px; display: flex; align-items: center; padding: 0 8px; } .menu-btn{ color: #fff !important; } .menu-btn:hover{ background: #000 !important; } .editor-container{ width: 100vw; height: calc(100vh - 40px); padding: 8px; background: #000; color: #fff; border: 1px solid transparent; } .editor-container:focus-visible{ outline: none; border-color: #fff; }`
如约而至的效果图:
重点来了,自定义我们的高亮节点
Slate提供了一个reanderElement方法,通过修改节点数据结构的type类型或者添加属性,就可以让我们轻松实现一个自定义节点。
js
复制代码
`// index.js import { useCallback, useState } from "react"; import { createEditor, Transforms } from "slate"; import { Slate, Editable, withReact, DefaultElement } from "slate-react"; import { Button } from 'antd' import { BulbOutlined } from '@ant-design/icons' import './index.css' // 自定义高亮节点 const HighBlock = (props) => { return ( // 添加slate相关属性 <div className="high-block" {...props.attributes}> <BulbOutlined /> {/* 展示高亮节点下的内容 */} {props.children} </div> ) } const SlateBox = ( ) => { const [editor] = useState(() => withReact(createEditor())) const [editorText, setEditorText] = useState([ { type: 'paragraph', children: [{ text: '这是一个slate内容的结构示例,每一段都是通过文本节点或者自定义节点的数组组成,文本节点必须包含text属性。' }] } ]) const renderElement = useCallback(props => { switch (props.element.type) { case 'highBlock': return <HighBlock {...props} /> default: return <DefaultElement {...props} /> } }, []) const addHighBlock = ( ) => { Transforms.insertNodes(editor, { type: 'highBlock', children: [{ text: '高亮节点默认值' }] }) } return ( <Slate editor={editor} initialValue={editorText}> <div className="editor-toolbar"> <Button icon={<BulbOutlined />} className="menu-btn" type="text" onClick={addHighBlock}></Button> </div> <Editable className="editor-container" renderElement={renderElement} /> </Slate> ) } export default SlateBox;`
添加我们自定义节点的样式:
css
复制代码
`/* index.css */ *{ box-sizing: border-box; } .editor-toolbar{ background: #242426; height: 40px; display: flex; align-items: center; padding: 0 8px; } .menu-btn{ color: #fff !important; } .menu-btn:hover{ background: #000 !important; } .editor-container{ width: 100vw; height: calc(100vh - 40px); padding: 8px; background: #000; color: #fff; border: 1px solid transparent; } .editor-container:focus-visible{ outline: none; border-color: #fff; } .high-block{ display: flex; padding: 16px; border-radius: 8px; background: rgba(242, 150, 44, .17); border: 1px solid #845117; margin: 16px 0; line-height: 24px; } .high-block .anticon-bulb{ color: #eb8f26; line-height: 28px; margin-right: 4px; }`
最后的实现效果图
以上只是一个Slate的简单入门示例,它还提供了许多诸如对选区、路径等操作方法,轻松实现滑动选择文字出现文字多音字提示等功能,大家可以去探索一下。
如果您觉得这篇文章有帮助,请点个赞吧~
相关文章
更多文章 →富文本2025-01-04
Monaco Editor,代码编辑器神器
本文介绍了 Monaco Editor 这款微软开源的基于浏览器的代码编辑器,它功能强大,包括语法高亮、代码补全等,具有轻量、可定制、跨平台等特点。文中阐述了其应用场景、使用方法、基本概念等,还列举了类似项目并给出项目地址,适合多种开发需求。 关联问题: Monaco支持哪些语言 如何定制Monaco 怎样优化界面效果 Monaco Editor是微软开源的一款基于浏览器的代码编辑器,它源自于Visual Studio Code(简称V...
学习
富文本2024-09-02
富文本格式粘贴的问题
回到最初的问题,利用富文本编辑器,编写邮件模板,或者说,提供一个编辑器,用来编写邮件。如果说编写邮件而已,大可以在 word 或者其他编辑器里写好内容,但这里的一个特点就是 占位符 。所以说,这是要保持邮件编辑器的功能,然后还能使用占位符。 前面也是利用了 实现了 占位符 ,且具有不可编辑的特点。另外也具有了编辑器的基础功能,如文字大小、颜色、背景、居中、缩进等等。在开发中,只关注于编辑器本身,即这个编辑器能编辑就可以了,忽略了 这个功...
学习
富文本2024-05-09
vue3集成tinymce
简介 看了一圈富文本编辑器,发现 和 比较符合自己的需求,功能上 更加丰富、简单一些。 吐槽 吐槽一下 的官网,给了 这个组件包,但是没想到就只是简单包装了一下(期初以为下载完这个包,引入vue组件内就完成了!),没想到如果只是单独引入这个包,是需要 的,而且是云托管方式去下载 ,导致反复看官网折腾了好久! 自托管集成方式 有两种方式,一种是使用包管理工具、另一种是zip包。 ,因为 还是挺大的,开发和打包过程影响编译时间。 以下面技术...
学习
富文本2024-05-08
新一代富文本编辑器框架lexical入门
是一款 基于 开发的网页端文本编辑框架,具备高拓展性架构,以高可靠性、易用性以及性能表现为核心设计思想。本身不与任何框架绑定,可独立于 、 使用(不过由于 与 的亲和性, 有 版)。使用者可在其基础上建立属于自己的独一无二的文本编辑器 目前在 内部,每天 通过 、 、 、 、 等产品服务千百万用户,稳定性及可靠性值得信赖 的核心包(上图左侧部分)只有22kb,其余能力以 形式提供。框架支持延迟加载, 可以在用户真正操作编辑器的时候再加载...
学习
富文本2024-05-06
再遇协同编辑:Yjs + Quill,文档协同编辑竟如此简单
通过上一篇文章 ,相信各位小伙伴对 OT 和 CRDT 协同算法有了一定的了解,并且对 Yjs 有了初步的认识,本文主要教会大家如何使用 Yjs 来实现 Quill 的协同编辑,以及针对 Yjs 的一些重要概念进行讲解。 因为协作需要服务端的支持,所有没有 demo,具体实现请 。 Yjs 介绍 官方介绍: 用于构建 Google Docs 和 Figma 等协作应用程序的模块化构建块 。 基于 CRDT ,帮助实现高性能的协作应用程序...
学习
富文本2024-04-25
Vue使用wangEditor富文本编辑器报错(ot find a descendant at path [0,1] in node: {“children“:[{“type“:“paragraph)_cannot find a descendant at path [0,1] in node
答案 时渲染dom报错问题: 每题的答案 修改文字样式后切换报错 解决办法: 在动态切换答案回显的同时删除 wangEditor 的实例然后异步重新创建一遍进行回显 代码片段:
学习
评论
请登录后发表评论
去登录