专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

2024 前端顶级 WYSIWYG 富文本编辑器 Slate 火了!

ins518 2024-09-21 00:37:06 技术文章 44 ℃ 0 评论

家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

什么是 Slate

Slate 可让开发者构建功能丰富、直观的编辑器,例如: Medium、Dropbox Paper 或 Google Docs 中的编辑器,而代码库不会陷入复杂性的泥潭。

Slate 可以轻松做到这一点,因为所有逻辑都是通过一系列插件实现的,因此永远不会受到 “核心” 中包含或不包含的内容的限制。 开发者可以将其视为构建在 React 之上的 contenteditable 的可插入实现,灵感来自于 Draft.js、Prosemirror 和 Quill 等库。

Slate 的设计原则如下:

  • 一流的插件:Slate 最重要的原则是“插件是一流的实体”,这意味着可以完全自定义编辑体验,构建像 Medium 或 Dropbox 的复杂编辑器,而不必违背库的假设。
  • 无架构核心:Slate 的核心逻辑对将要编辑的数据的模式做了很少的假设,这意味着库中没有任何假设,当需要超越最基本的用例时,这些假设会让开发者陷入困境。
  • 嵌套文档模型:Slate 使用的文档模型是一个嵌套的递归树,就像 DOM 本身一样。 这意味着可以为高级用例创建复杂的组件,例如:表或嵌套块引用。 但仅使用单个层次结构也很容易保持简单。
  • 与 DOM 并行: Slate 的数据模型基于 DOM,文档是一个嵌套树,使用选择(Selection)和范围(Range),并且公开所有标准事件处理程序,这意味着表或嵌套块引用等高级行为是可能的。 几乎任何可以在 DOM 中执行的操作,都可以在 Slate 中执行。
  • 直观的命令:Slate 文档是使用 “命令” 进行编辑的,这些命令被设计为高级且极其直观写入和读取,以便自定义功能尽可能具有表现力,从而极大地提高了推理代码的能力。
  • 协作就绪的数据模型:Slate 使用的数据模型(特别是如何将操作应用于文档)旨在允许在顶层进行协作编辑,因此,如果决定让编辑器进行协作,则无需重新考虑所有事情。
  • 明确 “核心” 界限: 借助插件优先的架构和无模式核心,“核心” 和 “自定义” 之间的界限变得更加清晰,这意味着核心体验不会陷入边缘情况。

目前 Slate 在 Github 通过 MIT 协议开源,有超过 28.6k 的 star、3.2k 的 fork、158k 的项目依赖量、代码贡献者 560+、妥妥的前端顶级开源项目。

如何使用 Slate

安装和 Slate 基础使用

Slate 是一个 monorepo,分为多个 npm 包,因此要安装只需要执行以下操作:

yarn add slate slate-react

还需要确保安装 Slate 的 peer 依赖项:

yarn add react react-dom

请注意,如果更愿意使用 Slate 的预打包版本可以使用 yarn 添加 slate 并检索打包的 dist/slate.js 文件! 安装 Slate 后,需要手动导入:

// Import React dependencies.
import React, {useState} from 'react'
// Import the Slate editor factory.
import {createEditor} from 'slate'

// Import the Slate components and React plugin.
import {Slate, Editable, withReact} from 'slate-react'

使用导入之前从一个空的 App 开始:

// Define our app...
const App = () => {
  return null
}

下一步是创建一个新的编辑器对象。 因为希望编辑器在渲染过程中保持稳定,因此使用不带 setter 的 useState 钩子:

const App = () => {
  // Create a Slate editor object that won't change across renders.
  const [editor] = useState(() => withReact(createEditor()))
  return null
}

当然,此时还没有渲染任何东西,所以不会看到任何变化。值得一提的是,如果使用 TypeScript 还需要使用 ReactEditor 扩展编辑器,并根据 TypeScript 文档添加注释。 下面的示例还包括本示例其余部分所需的自定义类型。

// TypeScript users only add this code
import {BaseEditor, Descendant} from 'slate'
import {ReactEditor} from 'slate-react'

type CustomElement = {type: 'paragraph'; children: CustomText[] }
type CustomText = {text: string}

declare module 'slate' {
  interface CustomTypes {
    Editor: BaseEditor & ReactEditor
    Element: CustomElement
    Text: CustomText
  }
}

接下来是渲染 <Slate> 上下文提供程序。

提供程序组件会跟踪 Slate 编辑器、插件、value、selection 以及发生的任何更改, 同时必须渲染在任何 <Editable> 组件之上。 但也可以使用 useSlate hooks 向其他组件(如工具栏、菜单等)提供编辑器状态。

const initialValue = [
  {
    type: 'paragraph',
    children: [{text: 'A line of text in a paragraph.'}],
  },
]

const App = () => {
  const [editor] = useState(() => withReact(createEditor()))
  // Render the Slate context.
  return <Slate editor={editor} initialValue={initialValue} />
}

可以将 <Slate> 组件视为为其下面的每个组件提供上下文。

Slate Provider 的 “value” 属性仅用作 editor.children 的初始状态。 如果代码依赖于替换 editor.children 应该直接替换,而不是依赖 “value” 属性来执行此操作。

这是与 <input> 或 <textarea> 等内容略有不同的思维模型,因为富文本文档更加复杂,经常需要在可编辑内容旁边包含工具栏、实时预览或其他复杂组件。通过共享上下文,其他组件可以执行命令、查询编辑器的状态等。

下一步是渲染 <Editable> 组件本身, 该组件的作用类似于 contenteditable。 无论在何处渲染,其都会为最近的编辑器上下文渲染可编辑的富文本文档。

const initialValue = [
  {
    type: 'paragraph',
    children: [{text: 'A line of text in a paragraph.'}],
  },
]

const App = () => {
  const [editor] = useState(() => withReact(createEditor()))
  return (
    // Add the editable component inside the context.
    <Slate editor={editor} initialValue={initialValue}>
      <Editable />
    </Slate>
  )
}

Slate 添加事件

以上示例已经安装了 Slate 并在页面上渲染,当用户输入内容可以看到更改, 但有时候想要做的不仅仅是键入纯文本字符串。

Slate 的伟大之处在于其非常容易定制,就像习惯的其他 React 组件一样,Slate 允许传入在某些事件上触发的处理程序。下面使用 onKeyDown 处理程序在按下某个键时更改编辑器的内容。

const initialValue = [
  {
    type: 'paragraph',
    children: [{ text: 'A line of text in a paragraph.' }],
  },
]

const App = () => {
  const [editor] = useState(() => withReact(createEditor()))

  return (
    <Slate editor={editor} initialValue={initialValue}>
      <Editable
        // Define a new handler which prints the key that was pressed.
        onKeyDown={event => {
          console.log(event.key)
        }}
      />
    </Slate>
  )
}

此时当在编辑器中按下某个键时,其相应的键码将打印在控制台中。

本文总结

本文主要和大家介绍 Slate 富文本编辑器,其可让开发者构建功能丰富、直观的编辑器,例如: Medium、Dropbox Paper 或 Google Docs 中的编辑器,而代码库不会陷入复杂性的泥潭。因为篇幅问题,关于 Slate 主题只是做了一个简短的介绍,但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。

参考资料

https://github.com/ianstormtaylor/slate

https://docs.slatejs.org/walkthroughs/01-installing-slate

https://vrite.io/blog/best-js-rich-text-editors-for-2023/

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表