tiptap-vue v0.1.4
tiptap-vue
一个基于tiptap2+vue3封装的富文本编辑器
Install
为了拥有更强的拓展能力,已将tiptap2的核心依赖独立出去,因此你在安装tiptap-vue时,需要同时安装tiptap2的依赖。
pnpm i @tiptap/pm @tiptap/core @tiptap/vue-3 @tiptap/suggestion tiptap-vue
Usage
全局安装使用
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import Tiptap from 'tiptap-vue'
import "tiptap-vue/dist/style.css"
import 'tiptap-vue/dist/style/icon/iconfont.css'
const app = createApp(App)
app.use(Tiptap)
app.mount('#app')
或者 单独使用
组件内单独引入
<script lang="ts" setup>
import { ref } from "vue";
import { Tiptap } from "tiptap-vue";
import "tiptap-vue/dist/style.css";
import 'tiptap-vue/dist/style/icon/iconfont.css'
const content = ref("");
</script>
最后使用组件
<template>
<Tiptap v-model="content"/>
</template>
自定义主题
默认是不引入主题样式的,因此你需要自己引入主题样式或者根据主题css变量自定义主题样式, 内置了3个主题,分别是prose-theme、prose-element、prose-arco
// default theme
import "tiptap-vue/dist/style/prose-theme.scss";
// element-ui theme
import "tiptap-vue/dist/style/prose-element.scss";
// arco-ui theme
import "tiptap-vue/dist/style/prose-arco.scss";
同时需要在你的Tiptap
组件上添加theme
属性,值为你引入的主题样式的类名
<Tiptap v-model="content" editable theme="prose-element"/>
Props
参数 | 说明 | 类型 | 默认值 | ||||
---|---|---|---|---|---|---|---|
v-model | 编辑器内容双向绑定 | string | - | ||||
theme | 主题 | string | prose-theme | ||||
extensions | 编辑器插件配置 | - | - | ||||
autofocus | 是否自动聚焦 | boolean \ | 'start' \ | 'end' \ | 'all' \ | number | false |
editable | 是否可编辑 | boolean | false | ||||
editorProps | tiptap文档 prosemirror文档 | object | - | ||||
parseOptions | parseOptions | - | - | ||||
output | 输出格式 | 'html' \ | 'json' \ | 'text' | html | ||
injectCSS | injectCSS | boolean | true | ||||
contentClass | 内部容器样式 | string | - | ||||
footerClass | 页脚样式 | string | - |
v-model
Type: string
编辑器向绑定的内容。
theme
Type: string
Default: prose-theme
主题样式设置。
<Tiptap v-model="content" theme="prose-element"/>
内置了3个主题,分别是 prose-theme
prose-element
prose-arco
// default theme
import "tiptap-vue/dist/style/prose-theme.scss";
// element-ui theme
import "tiptap-vue/dist/style/prose-element.scss";
// arco-ui theme
import "tiptap-vue/dist/style/prose-arco.scss";
编辑器内部的颜色、边框、圆角等大部分通过css变量调用,默认不包含任何样式文件,请根据需求自行引入或者自定义。
extensions
所有拓展
罗列出目前使用的所有拓展,如果你不想自定义拓展,可以直接使用defaultKit
套件,它包含了所有拓展,无需一个个单独引入。
如果你还是坚持自定义拓展,那么你可以参考下面的拓展列表,自行选择需要的拓展。
Required 必须安装的拓展,否则编辑器无法正常运行
Document
Text
Paragraph
marks
Bold
Code
Italic
Strike
Underline
Link
Highlight
Color
Superscript
Subscript
nodes
Heading
Blockquote
BulletList
OrderedList
HorizontalRule
ListItem
TaskItem
TaskList
CodeBlock
Table, TableCell, TableHeader, TableRow
Image
TableOfContents
Functionality
Placeholder
Dropcursor
Gapcursor
History
HardBreak
Typography
TextAlign
TextStyle
FocusClasses
TrailingNode
配置拓展
可以配置大多数扩展。添加一个对象并向其传递一个对象。.configure()
我们已经将以上所有的拓展都封装成了套件defaultKit
,你可以直接使用。当你的组件props未设置extensions
时,编辑器会自动使用defaultKit
。
我们强烈建议直接使用defaultKit
套件。
- 它包含了所有的拓展,无需一个个单独引入。
- 它支持对单个拓展进行禁用或者配置。
- 目前的气泡菜单和/斜杆菜单内置了许多拓展功能,并未做按需自动展示,如果未引入菜单中的功能拓展,将会导致菜单部分功能无法正常使用。
示例:
<Tiptap v-model="content" :extensions:"extensions" />
<script lang="ts" setup>
import {
Tiptap,
defaultKit, // 引入默认套件
} from "tiptap-vue";
const extensions = {
defaultKit.configure({
// 修改一个拓展的配置
Blockquote: {
HTMLAttributes: {
class: "blockquote",
},
},
})
}
</script>
你也可以禁用其中一个拓展,设置值为false
即可。
示例:
<Tiptap v-model="content" :extensions:"extensions" />
<script lang="ts" setup>
import {
Tiptap,
defaultKit, // 引入默认套件
TaskItem, // 单独引入某个拓展
} from "tiptap-vue";
const extensions = {
// 禁用其中一个拓展,设置值为false即可
defaultKit.configure({
TaskItem: false,
}),
// 单独引入某个拓展进行配置,或者二次封装自己的拓展再引入。
TaskItem.configure({
HTMLAttributes: {
class: "task-item",
},
}),
}
</script>
autofocus
Type: boolean
number
'start'
'end'
'all'
Default: false
编辑器创建时是否自动聚焦。
示例:
<Tiptap v-model="content" autofocus />
editable
Type: boolean
Default: true
编辑器是否可编辑。
示例:
<Tiptap v-model="content" editable />
editorProps
Type: object
Default: undefined
编辑器props设置,功能非常强大,详见tiptap文档、prosemirror文档
示例:
<Tiptap v-model="content" :editorProps="editorProps"/>
<script lang="ts" setup>
// ...
// 设置是否开启编辑器的拼写检查
const editorProps = {
attributes: {
spellcheck: false,
},
}
</script>
Events
编辑器生命周期钩子
<template>
<Tiptap v-model="content" editable @onCreate="onCreate"/>
</template>
<script lang="ts" setup>
onCreate({ editor }) {
// console.log(editor)
}
</script>
所有钩子:
onBeforeCreate
onCreate
onSelectionUpdate
onTransaction
onFocus
onBlur
onUpdate
onDestroy
Methods
图片拓展方法
图片上传是比较复杂的拓展。
- 目前支持复制粘贴上传(同时支持粘贴svg代码上传)、粘贴图片链接上传、拖拽上传、/斜杆菜单上传。
- 如果未配置图片上传方法,默认插入到编辑器的图片将会是base64格式的图片。/斜杆菜单上传会失效。
- 若希望插入到编辑器中的是网络图片地址,目前只能使用markdown格式的图片链接。
图片上传
一、onUpload?: (image: File | string) => Promise<attrs>
复制复制粘贴、拖拽上传。参数可能是个file对象也可能是一个url图片地址,上传时需要判断类型。
attrs
返回一个对象,必须包含src
、width
、height
三个属性。可以携带更多的属性,如alt
、title
等。
二、onCommandUpload?: () => Promise<attrs>
/斜杆菜单上传图片,需要自行处理打开文件选择框的逻辑
图片删除
onDelete?:(attrs) => void,
删除图片时会触发该方法。参数会自动接收到img属性,根据需求进行进一步逻辑处理,例如:从服务器删除图片。
图片属性解析
onParseSrc?: (src:string) => string
大多时候我们只需通过设置HTMLAttributes
就可以自定义拓展的属性。但在Image
拓展中有时候你可能希望更细粒度的去处理图片的src
地址,就可以使用该方法。
该方法参数会接收到图片的src
,最后需要return回处理之后的src
值,当你希望解析和存储的src地址不需要一致时应该用的到!
方法示例
<Tiptap v-model="content" :extensions:"extensions" />
<script lang="ts" setup>
import {
Tiptap,
defaultKit
} from "tiptap-vue";
const extensions = {
// 在defaultKit套件中引入Image拓展配置上传功能
defaultKit.configure({
Image: {
// 复制粘贴、拖拽上传
onUpload: (file) => {
return new Promise((resolve, reject) => {
// 会自动接收到图片的file对象、svg代码或者网络图片链接,你可以在这里处理上传业务
// ...
// 最后需要resolve上传后的图片Promise对象,包含src、width、height三个属性
resolve({
src: "https://img.yzcdn.cn/vant/cat.jpeg",
width: 100,
height: 100,
})
});
},
// /斜杆菜单上传
onCommandUpload: () => {
return new Promise((resolve, reject) => {
// 需要处理打开文件选择框的逻辑
// ...
// 最后需要resolve上传后的图片Promise对象,必须包含src、width、height三个属性
resolve({
src: "https://img.yzcdn.cn/vant/cat.jpeg",
width: 100,
height: 100,
// more...
})
});
},
// 删除图片事件(当点击删除图片时触发)
onDelete: (attrs) => {
// 会接收到图片的所有属性,你可以在这里处理更多的删除业务
// ...
},
// 细粒度处理图片src解析
onParseSrc:(src) => {
cosnt suffix = src.split('.')[src.length -1]
if(suffix === 'jpg'){
// ...进行逻辑处理
rerurn ...
}
return src
}
},
}),
}
</script>