保存到数据库
现在你已经学会了如何向 Slate 编辑器添加功能的基本知识,你可能想要知道如何保存你已经编辑过的内容,这样你就可以在之后返回应用程序并且加载它。
在这篇指南中,我们会像你展示如何添加逻辑,以便将你在 Slate 中编辑的内容保存到一个数据库中并在随后读取它。
让我们从一个基本的编辑器开始:
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
{
type: 'paragraph',
children: [{ text: '段落中的一段文本。' }],
},
])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Editable />
</Slate>
)
}
它将会渲染一个基本的 Slate 编辑器在页面上,随着你输入内容会发生变化。但是如果你刷新页面,所有内容都将回到一开始的时候 -- 什么都没有被保存!
我们需要做的是保存你在某个地方做的改变。对于这个例子来说,虽然我们仅仅使用了 Local Storage ,但是这会给你怎么保存数据带来灵感。
所以,在我们的 onChange
事件处理函数中,我们需要保存 value
:
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
{
type: 'paragraph',
children: [{ text: '段落中的一段文本。' }],
},
])
return (
<Slate
editor={editor}
value={value}
selection={selection}
onChange={value => {
setValue(value)
// 在 Local Storage 里保存值。
const content = JSON.stringify(value)
localStorage.setItem('content', content)
}}
>
<Editable />
</Slate>
)
}
现在无论何时你编辑页面,如果你查看 Local Storage,你应该会看到 content
的值已经被改变。
但是,如果你刷新页面,还是和之前一样,什么都不存在了。这是因为我们需要确保初始值是从同一个 Local Storage 读取的。就像这样:
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
// 如果 Local Storage 存在值,用它来更新初始值。
const [value, setValue] = useState(
JSON.parse(localStorage.getItem('content')) || [
{
type: 'paragraph',
children: [{ text: '段落中的一段文本。' }],
},
]
)
return (
<Slate
editor={editor}
value={value}
onChange={value => {
setValue(value)
const content = JSON.stringify(value)
localStorage.setItem('content', content)
}}
>
<Editable />
</Slate>
)
}
现在你应该能够保存刷新之间的变化了!
成功了 — 你已经有一个 JSON 对象在你的数据库了。
但是如果你想要保存的数据格式不是 JSON 呢? 没问题,只要你用不同的方式去序列化你的值就好了。比如说你想要保存纯文本而不是 JSON,我们可以编写一些逻辑来序列化和反序列化纯文本的值。
// 从 Slate 导入 `Node` 帮助函数接口。
import { Node } from 'slate'
// 定义一个参数为 `value` 返回值是纯文本的序列化函数。
const serialize = value => {
return (
value
// 返回这个 value 中每一个段落中的子节点的字符串内容。
.map(n => Node.string(n))
// 用换行符(用换行符来区分段落)来连接他们。
.join('\n')
)
}
// 定义一个参数是字符串返回值是 `value` 的反序列化函数
const deserialize = string => {
// 分隔字符串,返回一个包含value的child数组。
return string.split('\n').map(line => {
return {
children: [{ text: line }],
}
})
}
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
// 使用我们的反序列化函数来从 Local Storage 中读取数据。
const [value, setValue] = useState(
deserialize(localStorage.getItem('content')) || ''
)
return (
<Slate
editor={editor}
value={value}
onChange={value => {
setValue(value)
// 序列化 `value` 并将产生的字符串保存到 Local Storage。
localStorage.setItem('content', serialize(value))
}}
>
<Editable />
</Slate>
)
}
它也正常工作了!现在你保存的是纯文本。
你可以将你所喜欢的格式仿照这个策略去保存。你可以序列化为为 HTML,Markdown,甚至是根据你的实际情况定制的 JSON 格式。
🤖 请注意,虽然你可以用任何喜欢的方式去序列化值,但是他们需要被权衡。序列化过程本身是有成本的,有些格式可能比其他格式更加难以使用。通常来说,我们建议仅当在你有特殊用途的时候才编写自己的格式。另外,通常使用 Slate 默认的格式是最好的。