Skip to content

Vue 集成 ​

@axewo/fin-editor 提供 Vue 3 组件和组合式函数,将编辑器核心绑定到 Vue 的响应式系统。

FinEditor ​

主编辑器组件,开箱即用。

基础用法 ​

loading
loading
vue
<script setup lang="ts">
import { ref } from 'vue'
import { FinEditor } from '@axewo/fin-editor'
import '@axewo/fin-editor/index.scss'

const content = ref('<p>Hello World</p>')
</script>

<template>
  <fin-editor v-model="content" />
</template>

Props ​

属性类型默认值说明
modelValuestring''编辑器内容(v-model)
configEditorConfig{}编辑器配置
mode'edit' | 'view''edit'编辑模式
theme'light' | 'dark' | 'auto''light'主题
locale'zh-CN' | 'en-US''zh-CN'国际化语言
showToolbarbooleantrue显示工具栏
showLabelsbooleanfalse工具栏显示文字标签
showStatusBarbooleantrue显示状态栏
showWordCountbooleantrue状态栏显示字数
showFullscreenBtnbooleantrue显示全屏按钮
showBubblebooleantrue显示选中气泡菜单
bodyHeightstring | number—编辑器主体高度
loading

Events ​

事件参数说明
update:modelValuecontent: string内容变化(v-model 更新)
savecontent: string手动保存(Ctrl+S)
readyeditor: EditorInstance编辑器初始化完成
mode-changemode: EditorMode模式切换
loading

Expose API ​

通过 ref 可访问以下方法(defineExpose):

vue
<script setup lang="ts">
import { ref } from 'vue'

const editorRef = ref<InstanceType<typeof FinEditor>>()

function handleGetContent() {
  const html = editorRef.value?.getContent()
  console.log(html)
}
</script>

<template>
  <fin-editor ref="editorRef" v-model="content" />
</template>

暴露的方法:

方法返回值说明
getEditor()EditorInstance | null获取编辑器核心实例
getHTML()string获取 HTML 内容
getContent()string获取 HTML 内容(getHTML 别名)
getText()string获取纯文本内容(不含 HTML 标签)
getJSON()Record<string, any>获取 JSON 格式内容
setContent(content)void设置内容
executeCommand(name, ...args)any执行命令
isCommandActive(name)boolean检查命令状态

完整示例 ​

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FinEditor } from '@axewo/fin-editor'
import '@axewo/fin-editor/index.scss'

const content = ref('')
const editorRef = ref()
const isViewMode = ref(false)
const showLabels = ref(false)

function handleReady(editor) {
  console.log('编辑器就绪', editor)
}

function handleSave(html) {
  console.log('保存内容:', html)
}

function toggleMode() {
  isViewMode.value = !isViewMode.value
}

function insertHello() {
  editorRef.value?.executeCommand('toggleBold')
}
</script>

<template>
  <div class="editor-container">
    <!-- 工具栏外部控制 -->
    <div class="custom-controls">
      <button @click="toggleMode">
        {{ isViewMode ? '编辑' : '只读' }}
      </button>
      <button @click="insertHello">加粗</button>
      <label>
        <input v-model="showLabels" type="checkbox" />
        显示工具栏标签
      </label>
    </div>

    <fin-editor
      ref="editorRef"
      v-model="content"
      :mode="isViewMode ? 'view' : 'edit'"
      :show-labels="showLabels"
      body-height="400px"
      @ready="handleReady"
      @save="handleSave"
    />
  </div>
</template>

BubbleMenu ​

文本选中时的浮动工具栏,提供加粗/斜体/下划线/删除线等快捷操作。

Props ​

属性类型默认值说明
editorEditorInstance | null—编辑器核心实例
itemsstring[]['bold', 'italic', 'underline', 'strike', 'link']要显示的工具栏项 ID
showLabelsbooleanfalse是否显示标签文字

用法 ​

vue
<script setup lang="ts">
import { BubbleMenu } from '@axewo/fin-editor'
</script>

<template>
  <bubble-menu
    :editor="editorInstance"
    :items="['bold', 'italic', 'underline']"
    :show-labels="false"
  />
</template>

BubbleMenu 由 FinEditor 内部管理,一般不需要单独使用。通过 showBubble prop 控制即可。

loading

useEditor ​

无 UI 渲染的组合式函数,适合需要完全自定义 UI 的场景。

用法 ​

vue
<script setup lang="ts">
import { ref, shallowRef } from 'vue'
import { useEditor } from '@axewo/fin-editor'

const elementRef = ref<HTMLElement>()
const modelValue = ref('<p>Custom UI</p>')

const { editor, isReady, content } = useEditor({
  element: elementRef,
  modelValue,
})

function doCommand(cmd: string) {
  if (!editor.value) return
  editor.value.executeCommand(cmd)
}
</script>

<template>
  <div class="my-editor">
    <!-- 自定义工具栏 -->
    <div class="my-toolbar" v-if="isReady">
      <button @click="doCommand('toggleBold')">B</button>
      <button @click="doCommand('toggleItalic')">I</button>
      <button @click="doCommand('toggleUnderline')">U</button>
    </div>

    <!-- 编辑器内容区域 -->
    <div ref="elementRef" class="my-content" />
  </div>
</template>

Options ​

属性类型说明
elementRef<HTMLElement | undefined>编辑器挂载的 DOM 元素(template ref)
modelValueRef<string>双向绑定的内容
configPartial<EditorConfig>编辑器配置
modeRef<EditorMode>编辑模式
themeRef<EditorTheme>主题
localeRef<EditorLocale>国际化语言

Return ​

属性类型说明
editorShallowRef<EditorInstance | null>编辑器核心实例(浅响应)
isReadyRef<boolean>编辑器是否就绪
contentRef<string>当前内容(HTML)
modeRef<EditorMode>当前编辑模式
themeRef<EditorTheme>当前主题
localeRef<EditorLocale>当前语言

国际化 ​

编辑器内置 zh-CN(中文)和 en-US(英文)两种语言,默认中文。

vue
<template>
  <fin-editor v-model="content" locale="en-US" />
</template>

支持动态切换语言:

vue
<script setup lang="ts">
import { ref } from 'vue'
import type { EditorLocale } from '@axewo/fin-editor'

const locale = ref<EditorLocale>('zh-CN')
</script>

<template>
  <el-select v-model="locale">
    <el-option label="中文" value="zh-CN" />
    <el-option label="English" value="en-US" />
  </el-select>
  <fin-editor v-model="content" :locale="locale" />
</template>

国际化覆盖范围:工具栏按钮 tooltip、对话框标题与按钮、图片/链接编辑弹窗、状态栏文字。

撤销 / 重做 ​

CoreExtension 内置 History 扩展,开箱即用:

快捷键功能
Ctrl+Z撤销
Ctrl+Shift+Z重做
Ctrl+Y重做

工具栏也有撤销/重做按钮,当没有可撤销/重做的操作时自动禁用。

图片编辑 ​

插入的图片支持:

  • 拖拽调整大小:点击图片选中后,拖拽右下角/左下角圆点调整宽度
  • 编辑属性:选中图片后点击编辑按钮,可修改 Alt 文本、宽度和高度
  • 拖拽/粘贴上传:直接拖拽图片文件到编辑器或从剪贴板粘贴
vue
<script setup lang="ts">
import { ref } from 'vue'

const content = ref(`
  <p>选中下方图片可调整大小和编辑属性:</p>
  <img src="https://picsum.photos/600/300" alt="示例图片" width="100%" />
`)
</script>

<template>
  <fin-editor v-model="content" />
</template>

链接 ​

选中文本后可添加超链接,链接文字自动变色为主题色并带下划线。

快捷键功能
Ctrl+K插入/编辑链接

链接操作:

  • 插入链接:选中文本 → 点击工具栏链接按钮或 Ctrl+K → 输入 URL
  • 编辑链接:光标置于已有链接上 → Ctrl+K → 修改 URL
  • 取消链接:在链接编辑弹窗中点击"移除"按钮

BubbleMenu 中也集成了链接按钮,选中文本后可直接操作。

纯文本内容 ​

除了 getContent()(返回 HTML),还提供 getText() 获取纯文本:

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FinEditor } from '@axewo/fin-editor'

const editorRef = ref()
const plainText = ref('')

function showPlainText() {
  plainText.value = editorRef.value?.getText() || ''
}
</script>

<template>
  <fin-editor ref="editorRef" v-model="content" />
  <button @click="showPlainText">获取纯文本</button>
  <pre>{{ plainText }}</pre>
</template>

主题定制 ​

使用内置主题 ​

vue
<fin-editor v-model="content" theme="dark" />
<!-- 可选值:'light' | 'dark' | 'auto' -->

自定义 SCSS 变量 ​

scss
// 覆盖 CSS 变量
.fin-editor {
  --fin-editor-bg: #f5f5f5;
  --fin-editor-border: #e0e0e0;
  --fin-editor-toolbar-bg: #ffffff;
  --fin-editor-content-min-height: 300px;
  --fin-editor-radius: 8px;
  --fin-editor-font-size: 15px;
  --fin-editor-line-height: 1.8;
}

暗色主题变量 ​

暗色主题通过 .fin-editor--dark 类名下的 CSS 变量覆盖实现:

scss
.fin-editor--dark {
  --fin-editor-bg: #1e1e1e;
  --fin-editor-border: #333;
  --fin-editor-toolbar-bg: #252525;
  --fin-editor-text: #d4d4d4;
}

注册默认扩展 ​

@axewo/fin-editor 导出了一个 registerDefaults 便捷函数,等价于 FinEditor 内部注册的默认扩展集:

ts
import { registerDefaults } from '@axewo/fin-editor'
import { EditorInstance } from '@axewo/fin-editor'

const editor = new EditorInstance({ ... })
registerDefaults(editor)
// = editor.use(CoreExtension)       // Document/Paragraph/Text + History (undo/redo)
//         .use(TextStyleExtension)   // Bold/Italic/Underline/Strike/Color/Highlight
//         .use(ParagraphExtension)   // Heading/Align/Lists/Blockquote/HR
//         .use(LinkExtension)        // Link mark with colored text
//         .use(createImageExtension()) // Image node with resize + alt
//         .use(CodeBlockExtension)   // Code block with syntax highlighting

依赖关系 ​

@axewo/fin-editor
  ├── vue (peer)
  ├── element-plus (peer, 工具栏 UI)
  ├── @element-plus/icons-vue (peer)
  ├── @tiptap/vue-3 (peer)
  ├── @axewo/fin-editor (dep)
  ├── @axewo/fin-editor (dep)
  └── @axewo/fin-editor (peer, 用户自行导入 SCSS)