
slate-react library implemented with vue3
Why use it?
- :sparkles: Highly customizable features, use slate core at the bottom level
- :zap: The latest version of the core, use vue to reduce the number of re-renderings
- :coffee: This library provides the same usage as slate-react, design tends to be stable
- :point_right: Check out the live demo of all of the examples
How to use?
1. Install slate-vue3
npm install slate-vue3
2. Now, you can use it in vue-sfc :point_right: live demo
<script setup lang="ts">
import { h } from "vue"
import { Slate, Editable, defaultRenderLeaf, defaultRenderPlaceHolder } from "slate-vue3"
import { createEditor } from "slate-vue3/core"
import { withDOM } from "slate-vue3/dom"
import { withHistory } from "slate-vue3/history"
const initialValue = [
{
type: "paragraph",
children: [{ text: "Let's start"}]
}
]
const renderElement = ({ attributes, children }) => h("p", attributes, children)
const editor = withHistory(withDOM(createEditor(initialValue)))
</script>
<template>
<Slate :editor="editor" :render-element="renderElement" :render-leaf="defaultRenderLeaf"
:render-placeholder="defaultRenderPlaceHolder">
<Editable />
</Slate>
</template>
Component Props
Slate
editor
slate-editor instance, add DOM specific behaviors to the editor
const initialValue: Descendant[] = [{
type: 'paragraph',
children: [ { text: 'This is editable plain text, just like a <textarea>!' } ]
}]
const editor: DOMEditor = withDOM(createEditor(initialValue))
decorate
another type of text-level formatting, split text into leaves
function (entry: NodeEntry) => DecoratedRange[]
renderElement
a function used to render a custom component for a specific type of Element node in the Slate.js document model
export interface RenderElementProps {
children: VNode
element: Element
attributes: HTMLAttributes & {
"data-slate-node": "element"
"data-slate-inline"?: true
"data-slate-void"?: true
dir?: "rtl"
ref: any
};
}
function renderElement (props: RenderElementProps) => VNode
renderLeaf
customize the rendering of leaf nodes in the document tree of your Slate editor
export interface RenderLeafProps {
children: VNode
leaf: Text
text: Text
attributes: HTMLAttributes & {
"data-slate-leaf": true
};
}
renderPlaceholder
customize how the placeholder of the Slate.js Editable component is rendered when the editor is empty
export interface RenderPlaceholderProps {
children?: string
attributes: HTMLAttributes & VNodeProps & {
"data-slate-placeholder": boolean
dir?: "rtl"
};
}
Editable
customize style of editablearea, you can inherient other HTMLAttribute on it
interface EditableProps extends HTMLAttributes {
role?: string
readOnly: boolean
placeholder?: string
style?: CSSProperties
scrollSelectionIntoView: (
editor: DOMEditor,
domRange: globalThis.Range
) => void
is: string
}
Component Emits
onchange
any change in slate will trigger it
const onchange: (event: { operation?: Operation }) => void
onvaluechange
slate children change in slate will trigger it
const onvaluechange: (event: { operation?: Operation }) => void
onselectionchange
slate selection change in slate will trigger it
const onselectionchange: (event: { operation?: Operation }) => void
Hooks in slate-vue3
Get the current composing state of the editor. It deals with compositionstart, compositionupdate, compositionend events
const useComposing: () => Ref<boolean, boolean>
const composing = useComposing()
Get the current focused state of the editor
const useFocused: () => Ref<boolean, boolean>
const focused = useFocused()
Get the current readOnly state of the editor
const useReadOnly: () => Ref<boolean, boolean>
const readonly = useReadOnly()
Get the current selected state of an element
const useSelected: () => ComputedRef<boolean>
const selected = useSelected()
Get the current editor object from the context. Context whenever changes occur in the editor
const useEditor: () => DOMEditor
const editor = useEditor()
Get the current editor selection from the context
const useSelection: () => ComputedRef<BaseSelection>
const selection = useSelection()
Automatically bind ref to the real node when the component is mounted,This is important when rendering element nodes directly
const useInheritRef: (attribute: VNodeProps) => VNodeProps
const renderElement = (props: RenderElementProps) => {
const { attributes, children, element } = props
switch (element.type) {
case 'image':
return h(ImageComp, { element, ...useInheritRef(attributes) }, () => children)
default:
return h('p', attributes, children)
}
}
FAQ
1. Why do I have to pass renderFunction into component ?
This ensures that your rich text is as expected, and slave-vue3 provides some default rendering functions, you can directly use the default rendering behavior
2. Can I use jsx in slate-vue3 ?
Of coures yes, but we do not recommend it unless you have already configured jsx in the project, as a branch, using the h function directly is already simple enough
3. Why do rendering functions not use Vue components ?
Vue uses lazy updates, rendering with components generates additional state, which can cause unexpected results during updates, it would be better to use functions as branches directly
Directory Structure
- slate
slate core logic, update synchronously with slate
- slate-dom
Implementation of slate on dom, update synchronously with slate-dom
- slate-vue
Vue components for rendering slate editors
- slate-history
Same with slate-history
- slate-hyperscript
Same with slate-history
- share-tools
for special processing of Proxy data, obtain the raw pointer, isPlainObject declare
Compact Slate
reactive implement
- packages/slate/src/interfaces/text.ts 115:115
- packages/slate/src/create-editor.ts 94:94
- packages/slate/src/transforms-node/set-nodes.ts 18:18
- packages/slate/src/interfaces/text.ts 116:116
remove immer
- packages/slate/src/interfaces/node.ts 365:365
- packages/slate/src/interfaces/point.ts 103:103
- packages/slate/src/interfaces/range.ts 224:224
- packages/slate/src/interfaces/transforms/general.ts 322:333
other compact
- packages/slate/src/core/normalize-node.ts
- packages/slate-dom/src/plugin/dom-editor.ts 421:441