Slate 在 Vue 中如何正确绑定编辑器内容?

萌新.溢洋 阅读 68

我在用 Slate 做富文本编辑器,但和 Vue 的响应式数据绑定总是出问题。明明改了 editor.children,视图却没更新,是不是我哪里写错了?

试过直接赋值、用 Vue.set,甚至强制刷新组件,都没用。控制台也没报错,就是不渲染新内容。

<template>
  <div ref="editorRef" />
</template>

<script setup>
import { onMounted, ref } from 'vue'
import { createEditor } from 'slate'
import { withHistory } from 'slate-history'
import { Slate, Editable, withReact } from 'slate-react'

const editorRef = ref(null)
const editor = withHistory(withReact(createEditor()))

onMounted(() => {
  editor.children = [{ type: 'paragraph', children: [{ text: '初始内容' }] }]
})
</script>
我来解答 赞 14 收藏
二维码
手机扫码查看
2 条解答
IT人梓淇
你这问题常见啊,Slate 和 Vue 的结合有点坑。主要是 Slate 自己管理状态,Vue 的响应式系统察觉不到变化。你需要用一个中间的状态来触发 Vue 的重新渲染。

这样写试试:

import { onMounted, ref, watch } from 'vue'
import { createEditor } from 'slate'
import { withHistory } from 'slate-history'
import { Slate, Editable, withReact } from 'slate-react'

const editorRef = ref(null)
const editor = withHistory(withReact(createEditor()))
const value = ref([{ type: 'paragraph', children: [{ text: '初始内容' }] }])

onMounted(() => {
editor.children = value.value
})

watch(value, (newVal) => {
editor.children = newVal
})

function handleChange(newContent) {
value.value = newContent
}



然后模板里用 value 绑定:

<template>
<Slate :editor="editor" :value="value" @change="handleChange">
<Editable ref="editorRef" />
</Slate>
</template>


这样应该能解决问题,拿去改改。
点赞
2026-03-25 13:05
FSD-艳珂
你这代码里混用了 slate-react,这是最大的问题,Vue 里没法直接跑 React 组件。你得换成 slate-vue 这个库。

还有个关键点,Vue 3 的响应式系统会深度代理对象,这会搞坏 Slate 的内部状态判断,导致视图不更新或者极其卡顿。创建编辑器实例时,一定要用 markRaw 把它“防代理”处理,告诉 Vue 这个对象不需要响应式。

至于内容绑定,Slate 推荐的是单向数据流,别直接去赋值 editor.children,而是通过组件的 value prop 或者 v-model 来绑定。

试试下面这个改法,先把 slate-vue 装上:

<template>
<!-- 使用 slate-vue 提供的组件 -->
<Editable v-model="value" :editor="editor" />
</template>

<script setup>
import { ref, markRaw } from 'vue'
import { createEditor } from 'slate'
import { withHistory } from 'slate-history'
// 引入 slate-vue 的组件和插件
import { Editable, withVue } from 'slate-vue'

// 定义响应式数据存储内容
const value = ref([
{
type: 'paragraph',
children: [{ text: '初始内容' }],
},
])

// 核心:用 markRaw 包裹 editor,防止 Vue 劫持导致 Slate 失效
const editor = markRaw(withHistory(withVue(createEditor())))
</script>


这样改完后,你只需要操作 value 这个响应式变量,编辑器视图就会自动更新了,别去碰 editor.children
点赞 2
2026-03-04 12:04