深入理解Slate.js (2) 不可变数据与基本API

167 阅读2分钟

为什么要不可变数据

在上回讲到,Slate中以JSON作为数据范式,且其结构与DOM树是相对应的,因此经常容易出现多层嵌套的数据结构。
而大家都知道,在React中要想setState更新数据,就必须使得其引用地址产生改变,而常规的Object.assign或者...只能做到浅复制,如果使用deepclone又有性能方面的问题,因此Slate底层使用了Immer来操作不可变数据。这就导致了如果想要修改其内部的数据,就必须使用Slate对外暴露的API。

基本API

在介绍API之前,还是看一下Slate常规的数据结构。


如果我们想要将Second paragraph修改成Second line该如何做呢?如果想修改更深一层的link该如何做呢?
因此我们首先得了解Slate中最重要的概念:Path

Path

type Path = number[]
它是一个数字数组,代表了某个节点在整颗Slate节点树中的位置,比如First paragraph的Path就是[0], Link in paragraph的Path就是[1,1]
只要知道一个节点的Path,就可以很轻松的修改其内容,而修改就需要Transforms

Transforms

Transforms是Slate对外暴露的修改节点树的核心API,比如我们知道First paragraph的Path是[0], 如果想要将它改为First line,可以使用

Transforms.setNodes(editor, {children: [{text: 'First line']}, {at: [0]})

第一个参数代表着Slate的editor实例,第二个参数代表着想要修改的属性,而第三个参数代表着节点的位置。
而如果想要在其下添加一行,也很简单

Transforms.insertNodes(editor, {type: 'paragraph',children: [{text: 'New paragraph']}, {at: [0]})

而如果要删除第一行呢?

Transforms.removeNodes(editor, {at: [0]})

看上去是不是很简单?在大部分情况下,这三个API就已足够来完成增,删,改的操作。

然而

此刻问题就出现了。
首先,我如何精确定位到想要的节点的Path?难道每次都去遍历整颗树?
第二,我如果想删除Path1的节点后在Path2增加一个节点,那么删除了Path1后,Path2的位置不会改变吗?如何去追踪其位置?
这些问题会在进阶篇结合源码进行讲解。此刻先按下不表。