tiptap commands 命令介绍

tiptap编辑器提供了大量命令Commands,可以添加或更改内容、更改选择。如果你想用好tiptap编辑器,你需要掌握这些命令。

执行命令

Execute a command , tiptap 所有可用的命令都通过编辑器实例访问,比如将选中文本加粗的命令如下。

editor.commands.setBold();

链命令

Chain commands  大多数的命令可以组合到一个调用中,这比单独的函数调用要短和优雅一些,链命令以.chain()开头.run()结尾,将多个命令合并成一个事务,内容只更新一次事件也只触发一次,下面是链命令的代码例子。

editor
  .chain()
  .focus()
  .toggleBold()
  .run()

自定义链命令

链接命令时,事务被保留,如果要在自定义链命令,则需要使用事务并添加到其中,vue3 例子如下:

<template>
  <div class="editor">
    <editor-content :editor="state.editor" />
  </div>
</template>
<script setup lang="ts">
/*
 tiptap 中文文档
 https://www.itxst.com/tiptap/tutorial.html
*/
import { getCurrentInstance, onMounted, reactive, ref } from "vue";
import { Editor, EditorContent } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";  
import Link from '@tiptap/extension-link';

//重写扩展
const CustomLink= Link.extend({
  addCommands() {
  return {
    customCommand: attributes => ({ chain }) => {
      // Doesn’t work:
      // return editor.chain() …
      // Does work:
      return chain()
        .insertContent('foo!')
        .insertContent('bar!')
        .run()
    },
  }
}
})

const state = reactive({
  editor: new Editor({
    content: "<p>Tiptap 中文文档,回车输入数字看看效果</p>",
    extensions: [
      StarterKit,
      CustomLink 
    ],  
  }) as any,
});

onMounted(() => {
    setTimeout(()=>{
      //执行自定义链命令
      state.editor.chain().customCommand().run();
    },2000)
});
</script>
<style scoped>
.editor {
  margin: 10px 20px;
  width: 390px;
}
.editor:deep(.ProseMirror) {
  color: red;
  border: solid 1px #ddd;
  padding: 0px 6px;
  min-height: 160px;
}
.tools {
  display: flex;
  background-color: #eee;
  padding: 6px;
  justify-items: center;
}
.tools > label {
  color: #1512e6;
  cursor: pointer;
}
.tools > label + label {
  margin-left: 10px;
}
.editor:deep(a){
  color: #1512e6;
  cursor: pointer;
  text-decoration: underline;
}
</style>

内联命令

我们可以在一条链命令中插入业务逻辑,它可以和这个链命令在一个事务中执行(触发一次内容更新、触发一次事件),例子如下:

// 内联命令
editor
  .chain()
  .focus()
  .command(({ tr }) => {
    // 在事务中执行以下代码
    tr.insertText('hey, that’s cool!') 

    return true
  })
  .run()

试运行命令

有时您不想实际执行命令,只想知道是否可以执行命令,比如你执行editor.can().insertContent 它并不会插入内容到编辑器,它只会返回true或者false告诉你能否插入内容。

// 检测 insertContent 命令是否能执行
let res = editor.can().insertContent();
// 检测这条链命令是否能执行
let res = editor
  .can()
  .chain()
  .toggleBold()
  .toggleItalic()
  .run()

如何你是自己实现一个扩展,希望命令支持试运行,代码如下:.can().insertText()

export default (value) => ({ tr, dispatch }) => {

  if (dispatch) {
    tr.insertText(value)
  }

  return true
}
/*
如果无法理解,访问下面连接查看table扩展的实现代码
https://github.com/ueberdosis/tiptap/blob/998e6bbe79208e5ac7fea4f2161102f6c3f9af71/packages/extension-table/src/table.ts
*/

如果你是封装 tiptap 命令,则无需检查,tiptap 会为您完成

addCommands() {
  return {
    bold: () => ({ commands }) => {
      return commands.toggleMark('bold')
    },
  }
}

如果你只是包装一个普通的 ProseMirror 命令

import { exitCode } from '@tiptap/pm/commands'

export default () => ({ state, dispatch }) => {
  return exitCode(state, dispatch)
}

Try commands

执行第一个命令,如果第一个命令执行成功,那么不会往下执行命令列队,如果第一个命令执行失败,它将会一个一个的命令往下执行

editor.first(({ commands }) => [
  () => commands.undoInputRule(),
  () => commands.deleteSelection(),
  // …
])

也可以在命令中应用commands.first方法

export default () => ({ commands }) => {
  return commands.first([
    () => commands.undoInputRule(),
    () => commands.deleteSelection(),
    // …
  ])
}

下载教程 Demo

本教程Demo的源码点击这里下载,Tiptap Demo,下载完成后运行npm i初始化依赖包。