@tiptap/vue-2 知识点笔记-01

本文是关于@tiptap/vue-2编辑器实例API的详细说明,主要涵盖以下几部分核心内容:

  1. callbacks(回调函数) :介绍了编辑器在不同阶段触发的回调,包括beforeCreate(创建前初始化操作)、blur(失焦处理)、contentError(内容错误处理)、create(创建完成操作)、destroy(销毁时清理)等10个回调函数,每个函数均配有功能描述和具体使用示例,涉及资源准备、内容保存、错误处理等场景。

  2. capturedTransaction :为ProseMirror的Transaction类型,用于捕获编辑器当前处理的编辑事务(如输入、格式修改等),可用于监控操作(如判断是否包含插入操作)或干预事务执行,主要在transaction回调中使用。

  3. commandManager(命令管理器) :包含customState(自定义状态存储)、editor(关联编辑器实例)、rawCommands(原始命令集合)等属性和can(检查命令可执行性)、chain(创建命令链)等方法,详细说明了各部分的类型、功能及使用示例,核心价值在于统一管理命令的校验、调用和状态维护。

  4. contentComponent :作为编辑器内容区域的Vue 2组件实例,包含Vue内置属性(如$el$refs$store等)和自定义属性,详细解释了各内置属性的类型与功能,涉及DOM操作、组件通信、状态管理、插槽使用等场景,展示了如何通过该组件实例进行内容区域的相关操作。

编辑器实例的一些API

1 callbacks

js 复制代码
{
  callbacks: {
    beforeCreate,
    blur,
    contentError,
    create,
    destroy,
    drop,
    focus,
    paste,
    selectionUpdate,
    transaction,
    update,
  },
}

以下是对 @tiptap/vue-2 编辑器实例中 callbacks 对象包含的所有回调函数的详细解释及具体使用示例:

  • beforeCreate

    • 功能描述:编辑器实例创建前触发,可用于初始化前置操作(如环境检查、资源准备)
    • 使用示例:
    javascript 复制代码
    import { Editor } from '@tiptap/vue-2';
    const editor = new Editor({
      callbacks: {
        beforeCreate() {
          console.log('编辑器即将创建,准备初始化资源...'); 
          // 例如:预加载字体或检查扩展依赖
          if (!window.FontFace) {
            console.warn('当前环境不支持自定义字体');
          }
        }
      }
    })
  • blur

    • 功能描述:编辑器失去焦点时触发,可用于处理失焦后的逻辑(如保存草稿、隐藏工具栏)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        blur({ editor }) {       
          console.log('编辑器已失焦');       
          // 示例:失焦时自动保存内容       
          localStorage.setItem('editorDraft', editor.getHTML());       
          // 示例:隐藏自定义工具栏       
          document.getElementById('custom-toolbar').style.display = 'none';     
        }   
      } 
    });
  • contentError

    • 功能描述:内容解析或渲染出错时触发(如非法HTML结构),用于错误捕获和处理
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        contentError(error) {       
          console.error('内容处理出错:', error.message);       
          // 示例:错误时重置为默认内容       
          editor.setContent('<p>内容加载失败,请重新输入</p>');     
        }   
      } 
    });
  • create

    • 功能描述:编辑器实例创建完成并可用时触发,可用于初始化后的操作(如设置默认内容、绑定事件)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        create({ editor }) {       
          console.log('编辑器创建完成,可开始使用');       
          // 示例:从本地存储恢复内容       
          const savedContent = localStorage.getItem('editorContent');       
          if (savedContent) {         
            editor.setContent(savedContent);       
          }       
          // 示例:初始化后自动聚焦       
          editor.focus();     
        }   
      } 
    });
  • destroy

    • 功能描述:编辑器实例销毁时触发,用于清理资源(如移除事件监听、释放内存)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        destroy() {       
          console.log('编辑器已销毁,清理资源');       
          // 示例:移除全局事件监听       
          window.removeEventListener('resize', handleResize);       
          // 示例:清空本地存储的临时数据       
          localStorage.removeItem('editorDraft');     
        }   
      } 
    }); 
    // 后续调用销毁时触发 
    editor.destroy();
  • drop

    • 功能描述:拖放操作发生时触发(如拖拽文件或文本到编辑器),可用于自定义拖放逻辑
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        drop(event) {       
          // 阻止默认拖放行为(如需自定义处理)       
          event.preventDefault();       
          // 示例:处理拖放的文本内容       
          const droppedText = event.dataTransfer.getData('text');       
          if (droppedText) {         
            editor.insertContent(`<p>拖拽内容:${droppedText}</p>`);       
          }       
          // 示例:处理拖放的文件       
          const files = event.dataTransfer.files;       
          if (files.length) {         
            console.log('拖放的文件:', files);       
          }     
        }   
      } 
    });
  • focus

    • 功能描述:编辑器获得焦点时触发,可用于处理聚焦后的逻辑(如显示工具栏、记录聚焦时间)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        focus({ editor }) {       
          console.log('编辑器已聚焦');       
          // 示例:显示自定义工具栏      
          document.getElementById('custom-toolbar').style.display = 'flex';       
          // 示例:记录聚焦时间       
          window.editorFocusTime = new Date().getTime();     
        }   
      } 
    });
  • paste

    • 功能描述:粘贴操作发生时触发,可用于处理粘贴内容(如过滤格式、转换粘贴的文本)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        paste(event) {       
          // 示例:仅保留纯文本,移除HTML格式       
          const plainText = event.clipboardData.getData('text');       
          if (plainText) {         
            // 阻止默认粘贴行为         
            event.preventDefault();         
            // 插入纯文本内容         
            editor.insertContent(`<p>${plainText}</p>`);       
          }     
        }   
      } 
    });
  • selectionUpdate

    • 功能描述:选区(光标位置或选中范围)更新时触发,可用于同步选区状态(如更新工具栏按钮状态)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        selectionUpdate({ editor }) {       
          // 示例:检查当前选区是否处于加粗状态,更新工具栏按钮       
          const isBold = editor.isActive('bold');       
          document.getElementById('bold-btn').classList.toggle('active', isBold);       
          // 示例:获取当前选区范围       
          const { from, to } = editor.state.selection;       
          console.log('选区范围:', from, '-', to);     
        }   
      } 
    });
  • transaction

    • 功能描述:每次编辑事务(如输入、格式修改、删除)发生时触发,可用于监控所有编辑操作
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        transaction({ transaction, editor }) {       
          // 示例:记录所有编辑操作(用于审计或历史追踪)       
          console.log('执行编辑操作:', {         
            type: transaction.steps[0]?.constructor.name, 
            // 操作类型         
            time: new Date().toISOString()       
          });       
          // 示例:限制内容长度(超过1000字符阻止输入)       
          if (editor.getHTML().length > 1000 && transaction.steps.some(step => step.isInsertion)) {         
            transaction.setMeta('preventDefault', true); // 阻止本次操作       
          }     
        }   
      } 
    });
  • update

    • 功能描述:编辑器内容更新后触发(最终的内容变更),可用于实时保存或内容校验
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      callbacks: {     
        update({ editor }) {       
          console.log('内容已更新');       
          // 示例:实时保存到服务器       
          fetch('/api/save-content', {         
            method: 'POST',         
            body: JSON.stringify({ content: editor.getHTML() })       
          });       
          // 示例:内容校验(如检测敏感词)       
          const content = editor.getText();       
          if (content.includes('敏感词')) {         
            alert('内容包含不适当词汇');       
          }     
        }   
      } 
    });

2 capturedTransaction

js 复制代码
{
  capturedTransaction,
}
  • capturedTransaction

    • 类型:Transaction(ProseMirror)
    • 功能描述:捕获编辑器当前正在处理的「编辑事务」(如输入、格式修改、删除等操作的底层封装),可用于监控或干预事务执行
    • 使用示例:
    javascript 复制代码
    // 在transaction回调中获取捕获的事务 
    const editor = new Editor({   
      callbacks: {     
        transaction() {       
          // 打印当前捕获的事务详情(包含操作步骤、选区变化等)       
          console.log('当前编辑事务:', editor.capturedTransaction);       
          // 示例:判断事务是否包含插入操作       
          const hasInsert = editor.capturedTransaction.steps.some(step => step.isInsertion);       
          if (hasInsert) {         
            console.log('本次事务包含内容插入');       
          }     
        }   
      } 
    });

capturedTransaction :依赖 ProseMirror 的事务机制,仅在 transaction 回调或事务执行过程中有效,主要用于高级监控(如操作审计)或拦截(如限制特定操作)。

3 commandManager

js 复制代码
{
  commandManager: {
    customState,
    editor,
    rawCommands,
    can,
    chain,
    commands,
    hasCustomState,
    state,
  },
}

以下是对 @tiptap/vue-2 编辑器实例中 commandManager 对象下所有属性/方法的详细解释、类型说明及具体使用示例,结合实际开发场景覆盖核心用法:

  • commandManager.customState

    • 类型:Object
    • 功能描述:存储自定义命令的状态数据(如自定义扩展的开关状态、临时配置等),支持开发者扩展命令相关状态
    • 使用示例:
    javascript 复制代码
    // 1. 初始化时设置自定义状态 
    const editor = new Editor({   
      extensions: [     
        // 自定义扩展中注册customState     
        Extension.create({       
          name: 'custom-extension',       
          addCommands() {         
            return {          
              toggleCustom: () => ({ commands }) => {             
                // 修改customState           
              }         
            };       
          },       
          addStorage() {         
            return { isActive: false };       
          }     
        })   
      ],   
      commandManager: {     
        customState: {       
          isCustomMode: false, // 自定义状态:是否开启自定义模式       
          tempValue: ''        // 自定义状态:临时值     
        }   
      } 
    }); 
    // 2. 后续修改/读取customState 
    editor.commandManager.customState.isCustomMode = true; 
    console.log('当前自定义模式:', editor.commandManager.customState.isCustomMode);
  • commandManager.editor

    • 类型:Editor(Tiptap实例)
    • 功能描述:关联的顶层编辑器实例,可通过该属性直接访问编辑器核心功能(如内容操作、扩展管理)
    • 使用示例:
    javascript 复制代码
    // 通过commandManager获取编辑器实例,调用核心方法 
    const editor = new Editor({}); 
    // 示例1:获取当前内容HTML 
    const content = editor.commandManager.editor.getHTML(); 
    console.log('当前内容:', content); 
    // 示例2:设置内容 
    editor.commandManager.editor.setContent('<p>通过commandManager修改内容</p>'); 
    // 示例3:检查编辑器是否聚焦 
    const isFocused = editor.commandManager.editor.isFocused;
  • commandManager.rawCommands

    • 类型:Object
    • 功能描述:存储「原始命令」(未经过命令链包装的底层命令),直接对应扩展定义的基础操作
    • 使用示例:
    javascript 复制代码
    // 1. 加载Bold扩展(提供bold命令) 
    import { Bold } from '@tiptap/extension-bold'; 
    const editor = new Editor({ extensions: [Bold] }); 
    // 2. 通过rawCommands执行原始加粗命令 
    editor.focus(); // 先聚焦编辑器 
    editor.commandManager.rawCommands.bold(); // 执行原始加粗命令 
    // 3. 执行原始插入内容命令 
    editor.commandManager.rawCommands.insertContent('<p>原始命令插入内容</p>');
  • commandManager.can(command)

    • 类型:(command: string) => boolean
    • 功能描述: 检查指定命令是否可在当前选区/状态下执行(如判断光标处是否能加粗、插入表格)
    • 使用示例:
    javascript 复制代码
    import { Bold, Table } from '@tiptap/extensions'; 
    const editor = new Editor({ extensions: [Bold, Table] }); 
    // 示例1:检查当前是否可执行加粗命令 
    const canBold = editor.commandManager.can('bold'); 
    if (canBold) {   
      console.log('可以执行加粗命令');   
      editor.commandManager.commands.bold(); 
    } else {   
      console.log('当前选区无法加粗(如在代码块中)'); 
    } 
    // 示例2:检查是否可插入表格 
    const canInsertTable = editor.commandManager.can('insertTable'); 
    if (canInsertTable) {   
      editor.commandManager.commands.insertTable({ rows: 2, cols: 3 }); 
    }
  • commandManager.chain()

    • 类型:() => CommandChain
    • 功能描述:创建「命令链」,支持链式调用多个命令(自动处理命令依赖,如先聚焦再执行格式操作)
    • 使用示例:
    javascript 复制代码
    import { Bold, Italic, Heading } from '@tiptap/extensions'; 
    const editor = new Editor({ extensions: [Bold, Italic, Heading] }); 
    // 示例1:链式执行「聚焦→设置标题→加粗」 
    editor.commandManager.chain()   
      .focus() // 先聚焦编辑器   
      .setHeading({ level: 2 }) // 设置2级标题   
      .bold() // 加粗内容   
      .run(); // 执行命令链 
    // 示例2:链式执行「插入内容→斜体→选中文本」 
    editor.commandManager.chain()   
      .insertContent('<p>链式命令测试</p>')   
      .setTextSelection({ from: 3, to: 7 }) // 选中「命令」二字   
      .italic() // 斜体选中内容   
      .run();
  • commandManager.commands

    • 类型:Object
    • 功能描述:所有可用命令的集合(包含核心命令和扩展命令),直接调用即可执行操作
    • 使用示例:
    javascript 复制代码
    import { Link, Table } from '@tiptap/extensions'; 
    const editor = new Editor({ extensions: [Link, Table] }); 
    // 示例1:执行核心命令(设置内容、聚焦) 
    editor.commandManager.commands.setContent('<p>直接执行命令</p>'); 
    editor.commandManager.commands.focus(); 
    // 示例2:执行扩展命令(添加链接) 
    editor.commandManager.commands.setLink({ href: 'https://tiptap.dev', label: 'Tiptap官网' }); 
    // 示例3:执行表格命令(插入表格、添加行) 
    editor.commandManager.commands.insertTable({ rows: 2, cols: 2 }); 
    editor.commandManager.commands.addRowAfter();
  • commandManager.hasCustomState(key)

    • 类型:(key: string) => boolean
    • 功能描述:检查 customState 中是否存在指定键名的自定义状态,避免访问不存在的状态导致报错
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({   
      commandManager: {     customState: { isCustomMode: false }   } }); 
      // 示例1:检查存在的状态键 
      const hasModeState = editor.commandManager.hasCustomState('isCustomMode'); 
      console.log('是否存在isCustomMode状态:', hasModeState); // 输出true 
      // 示例2:检查不存在的状态键 
      const hasTempState = editor.commandManager.hasCustomState('tempValue'); 
      console.log('是否存在tempValue状态:', hasTempState); // 输出false 
      // 安全访问:存在则读取 
      if (hasModeState) {   
        console.log('当前模式:', editor.commandManager.customState.isCustomMode); 
      }
  • commandManager.state

    • 类型:Object
    • 功能描述:命令管理器的内部状态,包含命令执行记录、当前激活的命令类型等(主要用于调试或高级扩展)
    • 使用示例:
    javascript 复制代码
    const editor = new Editor({ extensions: [Bold] }); 
    // 1. 执行命令后查看state 
    editor.commandManager.commands.bold(); 
    // 2. 打印命令管理器状态(包含激活的标记、命令历史等) 
    console.log('命令管理器状态:', editor.commandManager.state); 
    // 示例:获取当前激活的标记(如是否加粗) 
    const activeMarks = editor.commandManager.state.activeMarks; 
    console.log('当前激活的标记:', activeMarks.map(mark => mark.type.name));
  1. commandManager 核心价值 :统一管理命令的「可执行性校验」(can)、「链式调用」(chain)和「状态维护」(customState/state),避免直接操作底层 API 导致的兼容性问题。
  2. 命令优先级chain() 命令链会自动处理命令依赖(如必须聚焦才能执行格式操作),推荐优先使用;rawCommands 适合需要跳过默认校验的场景(需谨慎使用)。

4 contentComponent

js 复制代码
{
  contentComponent: {
    $attrs,
    $children,
    $createElement,
    $el,
    $listeners,
    $options,
    $parent,
    $refs,
    $root,
    $scopedSlots,
    $slots,
    $store,
    $vnode,
    GetGroupPermission,
    GetPermission,
    __v_skip,
    _c,
    _data,
    _directInactive,
    _events,
    _hasHookEvent,
    _i18n,
    _inactive,
    _isBeingDestroyed,
    _isDestroyed,
    _isMounted,
    _isVue,
    _props,
    _provided,
    _renderProxy,
    _routerRoot,
    _scope,
    _self,
    _staticTrees,
    _subscribing,
    _uid,
    _vnode,
    _watcher,
  },
}

@tiptap/vue-2 中,contentComponent 本质是编辑器内容区域对应的 Vue 2 组件实例,其属性可分为两类:

  1. Vue 2 组件内置属性 :Vue 框架为所有组件实例提供的核心属性(如 $el$refs),占绝大多数;
  2. 自定义属性 :项目中基于业务需求扩展的属性(如 GetGroupPermissionGetPermission),非 Tiptap 原生。

以下是「内置属性」,逐一解释每个属性的功能并提供针对性示例(示例基于 Vue 2 语法):

  • contentComponent.$attrs

    • 类型:Object

    • 功能描述:包含父组件传递给当前组件、且未在 props 中声明的属性(不包含 classstyle

    • 使用示例:

      javascript 复制代码
      // 假设父组件给contentComponent传了`editor-id="my-editor"`和`theme="light"` 
      const contentComp = editor.contentComponent; 
      // 1. 读取未声明为props的属性 
      console.log('编辑器ID:', contentComp.$attrs['editor-id']);  // 输出"my-editor" 
      console.log('主题:', contentComp.$attrs.theme); // 输出"light" 
      // 2. 动态添加/修改attrs 
      contentComp.$attrs['readonly'] = true;
  • contentComponent.$children

    • 类型:Array<VueComponent>

    • 功能描述:当前组件的直接子组件实例列表(不包含孙组件),用于访问子组件方法/状态

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 遍历子组件,找到特定子组件 
      const toolbarComp = contentComp.$children.find(child => child.$options.name === 'EditorToolbar'); 
      // 2. 调用子组件方法 
      if (toolbarComp) {   
      toolbarComp.updateButtonStatus(); // 假设子组件有更新工具栏按钮状态的方法 
      } 
      // 3. 读取子组件属性 
      console.log('工具栏可见性:', toolbarComp.isVisible);
  • contentComponent.$createElement

    • 类型:Function

    • 功能描述:Vue 虚拟 DOM 构建函数(即 h 函数),用于手动创建虚拟节点(进阶用法)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 用$createElement创建虚拟节点(等价于h函数) 
      const newNode = contentComp.$createElement( 'div', { class: 'custom-note' }, ['这是手动创建的注释节点'] ); 
      // 2. 挂载到contentComponent的DOM中(需配合Vue实例方法) 
      contentComp.$el.appendChild(contentComp.$mount(newNode).$el);
  • contentComponent.$el

    • 类型:HTMLElement

    • 功能描述:当前组件对应的真实 DOM 元素,是操作编辑器内容区域 DOM 的直接入口

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 读取DOM属性 
      console.log('内容区域宽度:', contentComp.$el.offsetWidth); 
      // 2. 修改DOM样式 
      contentComp.$el.style.minHeight = '400px'; // 设最小高度 
      contentComp.$el.style.border = '1px solid #eee'; // 加边框 
      // 3. 绑定DOM事件(推荐用Vue的$on,但紧急场景可直接绑) 
      contentComp.$el.addEventListener('click', () => {
        console.log('内容区域被点击');
      });
  • contentComponent.$listeners

    • 类型:Object

    • 功能描述:包含父组件传递给当前组件的所有事件监听器(如 @update@focus

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看所有监听的事件 
      console.log('父组件监听的事件:', Object.keys(contentComp.$listeners)); // 如["update", "focus"] 
      // 2. 手动触发父组件绑定的事件(模拟内容更新) 
      if (contentComp.$listeners.update) {   
        contentComp.$listeners.update(editor.getHTML()); // 传递当前内容给父组件 
      } 
      // 3. 监听新事件(动态绑定) 
      contentComp.$on('custom-event', (data) => {
        console.log('收到自定义事件:', data);
      });
  • contentComponent.$options

    • 类型:Object

    • 功能描述:当前组件的配置选项,包含 namepropsmethodscreated 等生命周期钩子

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看组件名称和props定义 
      console.log('组件名:', contentComp.$options.name); // 如"TiptapContent" 
      console.log('组件props:', contentComp.$options.props); // 查看声明的props 
      // 2. 调用组件配置中的方法(若未挂载到实例上) 
      const initMethod = contentComp.$options.methods.initContent; 
      if (initMethod) {   
        initMethod.call(contentComp); // 用call绑定this为组件实例 
      } 
      // 3. 查看生命周期钩子 
      console.log('是否有mounted钩子:', !!contentComp.$options.mounted);
  • contentComponent.$parent

    • 类型:VueComponent

    • 功能描述:当前组件的父组件实例,用于访问父组件的状态或方法(避免深层嵌套依赖)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 访问父组件属性 
      console.log('父组件是否为编辑器容器:', contentComp.$parent.$options.name === 'EditorContainer'); 
      // 2. 调用父组件方法 
      if (contentComp.$parent.saveContent) {   
        contentComp.$parent.saveContent(editor.getHTML()); // 调用父组件的保存方法 
      } 
      // 3. 向上查找祖先组件(如需多层查找) 
      let ancestor = contentComp.$parent; 
      while (ancestor && ancestor.$options.name !== 'App') {   
        ancestor = ancestor.$parent; 
      } 
      console.log('找到根组件:', ancestor);
  • contentComponent.$refs

    • 类型:Object

    • 功能描述:包含当前组件中所有带 ref 属性的 DOM 元素或子组件实例,用于精准访问

    • 使用示例:

      javascript 复制代码
      // 假设contentComponent内部模板有:<div ref="contentWrapper"><p ref="firstPara"></p></div> 
      const contentComp = editor.contentComponent; 
      // 1. 访问带ref的DOM元素 
      const contentWrapper = contentComp.$refs.contentWrapper; 
      const firstPara = contentComp.$refs.firstPara; 
      console.log('第一个段落文本:', firstPara.textContent); 
      // 2. 访问带ref的子组件(如内部的格式工具栏) 
      const formatToolbar = contentComp.$refs.formatToolbar; 
      if (formatToolbar) {   
        formatToolbar.toggleBold(); // 调用子组件方法 
      }
  • contentComponent.$root

    • 类型:VueComponent

    • 功能描述:当前 Vue 应用的根组件实例(通常是 new Vue({...}) 创建的实例),用于全局访问

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 访问根组件的全局状态 
      console.log('根组件全局主题:', contentComp.$root.theme); 
      // 2. 调用根组件的全局方法 
      contentComp.$root.showGlobalToast('内容已保存'); // 假设根组件有全局提示方法 
      // 3. 访问根组件的$store(Vuex) 
      if (contentComp.$root.$store) {   
        console.log('用户信息:', contentComp.$root.$store.state.user); 
      }
  • contentComponent.$scopedSlots

    • 类型:Object

    • 功能描述:包含父组件传递的「作用域插槽」(带参数的插槽),用于动态渲染插槽内容

    • 使用示例:

      javascript 复制代码
      // 假设父组件给contentComponent传了作用域插槽:<template #customFooter="{ contentLength }">...</template> 
      const contentComp = editor.contentComponent; 
      // 1. 检查是否有指定作用域插槽 
      if (contentComp.$scopedSlots.customFooter) {   
        // 2. 渲染作用域插槽(传递参数)   
        const footerVNode = contentComp.$scopedSlots.customFooter({     
          contentLength: editor.getHTML().length // 传递内容长度给插槽   
        });   
        // 3. 挂载到DOM(需先转为真实DOM)   
        const footerEl = contentComp.$mount(footerVNode).$el;   
        contentComp.$el.appendChild(footerEl); 
      }
  • contentComponent.$slots

    • 类型:Object

    • 功能描述:包含父组件传递的「普通插槽」(无参数),如默认插槽、具名插槽

    • 使用示例:

      javascript 复制代码
      // 假设父组件给contentComponent传了具名插槽:<template #toolbar>...</template> 
      const contentComp = editor.contentComponent; 
      // 1. 访问默认插槽(无name的插槽) 
      const defaultSlot = contentComp.$slots.default; 
      // 2. 访问具名插槽 
      const toolbarSlot = contentComp.$slots.toolbar; 
      // 3. 渲染插槽内容(若存在) 
      if (toolbarSlot) {   
        const toolbarEl = contentComp.$mount(toolbarSlot[0]).$el;   
        contentComp.$el.prepend(toolbarEl); // 插入到内容区域顶部 
      }
  • contentComponent.$store

    • 类型:Vuex.Store

    • 功能描述:若项目集成了 Vuex,此属性为全局 Store 实例,用于访问/修改全局状态

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 读取Vuex状态 
      console.log('当前用户权限:', contentComp.$store.getters.userPermission); 
      // 2. 提交mutation修改状态 
      contentComp.$store.commit('SET_EDITOR_CONTENT', editor.getHTML()); 
      // 3. 分发action执行异步操作 
      contentComp.$store.dispatch('saveEditorContent', editor.getHTML());
  • contentComponent.$vnode

    • 类型:VNode

    • 功能描述:当前组件的虚拟节点(Vue 内部用于描述 DOM 结构的对象),主要用于调试

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看虚拟节点的基本信息 
      console.log('虚拟节点标签:', contentComp.$vnode.tag); // 如"vue-component-10-TiptapContent" 
      console.log('虚拟节点数据:', contentComp.$vnode.data); // 包含class、style等 
      // 2. 查看子虚拟节点 
      console.log('子虚拟节点数量:', contentComp.$vnode.children.length); 
      // 3. 调试用:对比虚拟节点与真实DOM 
      if (contentComp.$vnode.elm === contentComp.$el) {
        console.log('虚拟节点与真实DOM匹配');
      }
  • contentComponent.__v_skip

    • 类型:boolean

    • 功能描述:Vue 内部标记,用于跳过某些组件的响应式处理(通常为 true,开发者无需修改)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; // 仅用于查看,不建议修改 
      console.log('是否跳过响应式处理:', contentComp.__v_skip); // 输出true(Tiptap内部优化)
  • contentComponent._c

    • 类型:Function

    • 功能描述:$createElement 的别名(Vue 内部简写),功能完全一致

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 用_c创建虚拟节点(等价于$createElement) 
      const btnNode = contentComp._c(
        'button',   
        { 
          on: { click: () => console.log('按钮点击') } 
        },   
        ['点击我'] 
      ); 
      // 挂载到DOM 
      contentComp.$el.appendChild(contentComp.$mount(btnNode).$el);
  • contentComponent._data

    • 类型:Object

    • 功能描述:组件实例的响应式数据存储(包含 data 选项中定义的属性),不建议直接修改

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看响应式数据 
      console.log('组件响应式数据:', contentComp._data); // 如{ isFocused: true, content: '<p>...</p>' } 
      // 2. 间接修改(推荐用$set保证响应式) 
      contentComp.$set(contentComp._data, 'isFocused', false); // 不建议直接赋值:contentComp._data.isFocused = false
  • contentComponent._directInactive

    • 类型:boolean

    • 功能描述:Vue 内部用于标记指令是否处于非激活状态(开发者无需关注,仅调试用)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      console.log('指令是否非激活:', contentComp._directInactive); // 通常为false
  • contentComponent._events

    • 类型:Object

    • 功能描述:存储当前组件绑定的所有事件监听器(包含 $on 绑定的事件),$listeners 的补充

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看所有绑定的事件 
      console.log('组件绑定的事件:', Object.keys(contentComp._events)); // 如["focus", "custom-event"] 
      // 2. 手动触发事件 
      contentComp._events.focus.forEach(cb => cb()); // 触发所有focus监听器
  • contentComponent._hasHookEvent

    • 类型:boolean

    • 功能描述: Vue 内部标记,用于判断组件是否有生命周期钩子对应的事件监听(开发者无需修改)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      console.log('是否有钩子事件监听:', contentComp._hasHookEvent); // 如true(若有监听created、mounted等) 
  • contentComponent._i18n

    • 类型:Object

    • 功能描述:若项目集成了 vue-i18n,此属性为国际化实例,用于多语言处理

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 翻译文本 
      console.log('翻译"保存":', contentComp._i18n.t('common.save')); 
      // 2. 切换语言 
      contentComp._i18n.locale = 'en'; // 切换为英文 
      console.log('翻译"保存"(英文):', contentComp._i18n.t('common.save'));
  • contentComponent._inactive

    • 类型:boolean

    • 功能描述:Vue 内部用于标记组件是否处于非激活状态(如 keep-alive 包裹的组件失活时为 true

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; // 监听组件激活/失活事件 
      contentComp.$on('activated', () => {   
        console.log('组件激活:', contentComp._inactive); // 输出false 
      }); 
      contentComp.$on('deactivated', () => {   
        console.log('组件失活:', contentComp._inactive); // 输出true 
      });
  • contentComponent._isBeingDestroyed

    • 类型:boolean

    • 功能描述:Vue 内部标记,用于判断组件是否正在销毁中(销毁过程中为 true,销毁后为 false

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; // 监听destroyed钩子,查看状态 
      contentComp.$on('destroyed', () => {   
        console.log('是否正在销毁:', contentComp._isBeingDestroyed); // 输出false 
      }); 
      // 手动销毁组件 
      editor.destroy(); 
      console.log('销毁中状态:', contentComp._isBeingDestroyed); // 输出true
  • contentComponent._isDestroyed

    • 类型:boolean

    • 功能描述:Vue 内部标记,用于判断组件是否已完全销毁(销毁后为 true

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; // 初始状态 
      console.log('是否已销毁:', contentComp._isDestroyed); // 输出false 
      // 销毁后查看 
      editor.destroy(); 
      console.log('是否已销毁:', contentComp._isDestroyed); // 输出true 
      // 销毁后避免操作 
      if (!contentComp._isDestroyed) {
        contentComp.$el.style.display = 'none';
      }
  • contentComponent._isMounted

    • 类型:boolean

    • 功能描述:Vue 内部标记,用于判断组件是否已挂载到 DOM(挂载后为 true

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; // 监听mounted钩子 
      contentComp.$on('mounted', () => {   
        console.log('是否已挂载:', contentComp._isMounted); // 输出true   
        // 挂载后操作DOM   
        contentComp.$el.style.minHeight = '300px'; 
      }); // 初始状态(未挂载时) 
      console.log('是否已挂载:', contentComp._isMounted); // 输出false
  • contentComponent._isVue

    • 类型:boolean

    • 功能描述:Vue 内部标记,用于判断对象是否为 Vue 组件实例(始终为 true

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      console.log('是否为Vue实例:', contentComp._isVue); // 输出true 
      // 用于类型判断 
      function isVueComponent(obj) {
        return obj && obj._isVue;
      } 
      console.log('contentComponent是否为Vue组件:', isVueComponent(contentComp)); // 输出true
  • contentComponent._props

    • 类型:Object

    • 功能描述:存储组件 props 的实际值(包含父组件传递的 props 和默认值)

    • 使用示例:

      javascript 复制代码
      // 假设contentComponent的props定义:{ editor: { type: Object }, theme: { type: String, default: 'light' } } 
      const contentComp = editor.contentComponent; 
      // 1. 查看props值 
      console.log('传递的editor实例:', contentComp._props.editor === editor); // 输出true 
      console.log('主题props:', contentComp._props.theme); // 输出"light" 
      // 2. 监听props变化(推荐用watch,而非直接监听_props) 
      contentComp.$watch('_props.theme', (newTheme) => {
        console.log('主题变更为:', newTheme);
      });
  • contentComponent._provided

    • 类型:Object

    • 功能描述:存储通过 provide/inject API 提供给子组件的数据(父组件 provide 的内容)

    • 使用示例:

      javascript 复制代码
      // 假设父组件通过provide提供:provide() { return { editorInstance: this.editor } } 
      const contentComp = editor.contentComponent; // 查看provide的数据 
      console.log('父组件提供的editor实例:', contentComp._provided.editorInstance === editor); // 输出true
  • contentComponent._renderProxy

    • 类型:VueComponent

    • 功能描述:Vue 内部用于代理组件渲染的对象(开发者无需直接操作,调试时可查看渲染上下文)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; // 查看渲染代理的上下文 
      console.log('渲染代理的this:', contentComp._renderProxy === contentComp); // 输出true(Vue 2中通常为同一对象) 
      console.log('渲染代理的方法:', contentComp._renderProxy.updateContent); // 访问组件方法
  • contentComponent._routerRoot

    • 类型:VueComponent

    • 功能描述:若项目集成 vue-router,此属性指向 Vue Router 的根实例 (即挂载 $router$route 的根组件),用于在组件中间接访问路由功能(优先直接用 $router/$route

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 访问路由根实例的$router(等价于contentComp.$router) 
      const router = contentComp._routerRoot.$router; 
      console.log('当前路由路径:', router.currentRoute.path); 
      // 2. 调用路由跳转(等价于this.$router.push) 
      router.push('/editor-history'); 
      // 3. 对比:直接用$router更简洁 
      console.log('直接访问$router路径:', contentComp.$router.currentRoute.path);
  • contentComponent._scope

    • 类型:Object

    • 功能描述:Vue 2 内部用于存储 组件作用域相关数据 的对象(如作用域插槽的参数、动态指令的上下文),开发者几乎无需直接操作,仅调试作用域问题时可能用到

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看作用域数据(主要用于调试) 
      console.log('组件作用域数据:', contentComp._scope); // 可能包含插槽参数、指令绑定值等 
      // 2. 场景:若作用域插槽参数异常,可查看_scope 
      const slotScope = contentComp._scope.$scopedSlots?.customTool || {}; 
      console.log('自定义插槽作用域参数:', slotScope);
  • contentComponent._self

    • 类型:VueComponent

    • 功能描述:指向 组件实例本身 ,是 Vue 内部为避免 this 指向混乱而定义的别名(等价于组件实例 this),日常开发无需使用

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 验证_self与组件实例的一致性 
      console.log('是否指向自身:', contentComp._self === contentComp); // 输出 true 
      // 2. 内部使用场景(模拟Vue源码逻辑) 
      const componentInstance = contentComp._self; 
      componentInstance.$el.style.border = '1px solid #ccc'; // 等价于 contentComp.$el.style.border = '1px solid #ccc'
  • contentComponent._staticTrees

    • 类型:Array<VNode>

    • 功能描述:存储组件模板中的 静态虚拟节点树(如固定文本、无动态绑定的 DOM 结构),Vue 用于优化静态内容的渲染性能(避免重复创建虚拟节点)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看静态节点树(仅包含静态内容) 
      console.log('静态虚拟节点数量:', contentComp._staticTrees?.length || 0); 
      // 2. 调试静态内容渲染:若静态内容异常,可检查_staticTrees 
      if (contentComp._staticTrees) {   
        const firstStaticNode = contentComp._staticTrees[0];   
        console.log('第一个静态节点标签:', firstStaticNode.tag); // 如"div"   
        console.log('第一个静态节点内容:', firstStaticNode.text); // 如"编辑器工具栏" 
      }
  • contentComponent._subscribing

    • 类型:boolean

    • 功能描述:Vue 内部用于标记 组件是否正在订阅响应式数据 的状态(如 watch 初始化、computed 依赖收集阶段),开发者无需修改,仅调试响应式问题时参考

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看订阅状态(通常为false,仅在依赖收集时为true) 
      console.log('是否正在订阅响应式数据:', contentComp._subscribing); 
      // 2. 调试响应式:若数据未触发更新,可检查订阅状态 
      contentComp.$watch('isFocused', (newVal) => {   
        console.log('聚焦状态变化时的订阅状态:', contentComp._subscribing); // 此时可能为true(依赖收集) 
      });
  • contentComponent._uid

    • 类型:number

    • 功能描述:Vue 为每个组件实例分配的 唯一标识 ID(自增整数),用于区分不同组件实例(如列表渲染中的组件、动态创建的组件)

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 获取当前组件的唯一ID 
      console.log('contentComponent唯一ID:', contentComp._uid); // 如 123 
      // 2. 场景:区分多个编辑器实例的contentComponent 
      const editor1 = new Editor({ ... }); 
      const editor2 = new Editor({ ... }); 
      console.log('编辑器1 contentComponent ID:', editor1.contentComponent._uid); // 如 123 
      console.log('编辑器2 contentComponent ID:', editor2.contentComponent._uid); // 如 124 
      // 3. 筛选特定组件实例(若有多个组件列表) 
      const allComponents = [editor1.contentComponent, editor2.contentComponent]; 
      const targetComp = allComponents.find(comp => comp._uid === 123);
  • contentComponent._vnode

    • 类型:VNode

    • 功能描述:指向当前组件对应的 虚拟节点对象(Vue 用于描述 DOM 结构的抽象层),包含节点标签、属性、子节点等信息,可用于调试 DOM 渲染问题

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看虚拟节点基本信息 
      console.log('组件虚拟节点标签:', contentComp._vnode.tag); // 如"vue-component-15-TiptapContent" 
      console.log('虚拟节点数据(属性/样式):', contentComp._vnode.data); // 包含class、style等 
      // 2. 查看子虚拟节点(组件内部的DOM结构) 
      const childVNodes = contentComp._vnode.children || []; console.log('子虚拟节点数量:', childVNodes.length); // 3. 调试渲染异常:若真实DOM与预期不符,检查_vnode if (childVNodes[0]) {   console.log('第一个子节点类型:', childVNodes[0].tag); // 如"p"(段落节点) }
  • contentComponent._watcher

    • 类型:Watcher

    • 功能描述:指向当前组件的 根 Watcher 实例(Vue 用于监听组件模板依赖,触发组件重新渲染),是组件响应式渲染的核心,开发者仅在高级调试时使用

    • 使用示例:

      javascript 复制代码
      const contentComp = editor.contentComponent; 
      // 1. 查看根Watcher(仅调试用) 
      console.log('组件根Watcher:', contentComp._watcher); 
      // 2. 强制触发组件重新渲染(模拟Watcher执行,不推荐日常使用) 
      if (contentComp._watcher) {   
        contentComp._watcher.run(); 
        // 强制组件重新渲染,解决某些渲染异常问题 
      } 
      // 3. 查看Watcher依赖的响应式数据(高级调试) 
      const dependencies = contentComp._watcher.deps || []; 
      console.log('根Watcher依赖的响应式数据数量:', dependencies.length);

4.1 关键说明

  1. 底层属性特性 :上述属性多为 Vue 2 框架内部实现细节,不建议在业务代码中直接修改 (如 _subscribing_watcher),仅推荐在调试渲染异常、响应式问题或实现高级功能(如动态组件管理)时参考。
  2. 替代方案 :日常开发中,优先使用 Vue 暴露的「官方 API」而非底层属性:
    • 访问路由用 this.$router 而非 _routerRoot.$router
    • 操作 DOM 用 this.$elthis.$refs 而非直接修改 _vnode
    • 组件通信用 props/events/Vuex 而非 _parent/_scope
  3. Tiptap 适配性contentComponent 是 Tiptap 对 Vue 组件的封装,其底层属性行为与普通 Vue 2 组件完全一致,若遇到属性相关问题,可参考 Vue 2 官方文档的「实例属性」章节。
相关推荐
写不来代码的草莓熊21 小时前
vue前端面试题——记录一次面试当中遇到的题(8)
前端
仰望.21 小时前
vue 下拉框 vxe-select 实现人员选择下拉列表
前端·javascript·vue.js·vxe-ui
丘耳21 小时前
@tiptap/vue-2 知识点笔记-03
前端·javascript·vue.js
丘耳21 小时前
@tiptap/vue-2 知识点笔记-05
前端·javascript·vue.js
m0_6161884921 小时前
使用el-table实现行内编辑功能
前端·javascript·vue.js
Mintopia21 小时前
🧬 AIGC 内容溯源技术:Web 平台如何识别 AI 生成内容?
前端·javascript·aigc
.NET修仙日记21 小时前
jQuery面试题精选:从基础到高级
前端·javascript·jquery
Mintopia21 小时前
⚙️ Next.js 缓存 + 分页优化:让你的页面速度快得像量子比特 🧠✨
前端·全栈·next.js
玲小珑21 小时前
LangChain.js 完全开发手册(十五)实战综合项目一:智能文档处理系统
前端·langchain·ai编程