refactor(editor): 重构工具栏动作处理逻辑
将工具栏动作处理逻辑从 useEditor 组合式函数移至 LivePreviewEditor 组件内部,通过事件直接触发动作执行,简化组件间通信并提高代码内聚性。移除 EditorToolbar 组件中对 useEditor 的依赖,改为直接发射 'action' 事件。
This commit is contained in:
parent
3d31989d4b
commit
c4b9aaaaca
BIN
public/logo.png
BIN
public/logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 8.0 KiB |
|
|
@ -7,7 +7,7 @@
|
|||
<template #icon><span style="font-weight: bold; font-size: 14px;">H</span></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key }) => triggerAction('heading', key)">
|
||||
<a-menu @click="({ key }) => $emit('action', 'heading', key)">
|
||||
<a-menu-item :key="1"><span style="font-size: 1.6em; font-weight: bold;">H1 标题</span></a-menu-item>
|
||||
<a-menu-item :key="2"><span style="font-size: 1.4em; font-weight: bold;">H2 标题</span></a-menu-item>
|
||||
<a-menu-item :key="3"><span style="font-size: 1.2em; font-weight: bold;">H3 标题</span></a-menu-item>
|
||||
|
|
@ -21,36 +21,36 @@
|
|||
<a-divider type="vertical" style="height: 1.2em; background-color: var(--border-color);" />
|
||||
|
||||
<!-- 文本样式 -->
|
||||
<a-button type="text" size="small" @click="triggerAction('bold')" title="加粗 (Ctrl+B)">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'bold')" title="加粗 (Ctrl+B)">
|
||||
<template #icon><BoldOutlined /></template>
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="triggerAction('italic')" title="斜体 (Ctrl+I)">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'italic')" title="斜体 (Ctrl+I)">
|
||||
<template #icon><ItalicOutlined /></template>
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="triggerAction('strike')" title="删除线">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'strike')" title="删除线">
|
||||
<template #icon><StrikethroughOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
<a-divider type="vertical" style="height: 1.2em; background-color: var(--border-color);" />
|
||||
|
||||
<!-- 引用与代码 -->
|
||||
<a-button type="text" size="small" @click="triggerAction('quote')" title="引用">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'quote')" title="引用">
|
||||
<template #icon><MessageOutlined /></template>
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="triggerAction('inlineCode')" title="行内代码">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'inlineCode')" title="行内代码">
|
||||
<template #icon><CodeOutlined /></template>
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="triggerAction('link')" title="链接">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'link')" title="链接">
|
||||
<template #icon><LinkOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
<a-divider type="vertical" style="height: 1.2em; background-color: var(--border-color);" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<a-button type="text" size="small" @click="triggerAction('unorderedList')" title="无序列表">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'unorderedList')" title="无序列表">
|
||||
<template #icon><UnorderedListOutlined /></template>
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="triggerAction('orderedList')" title="有序列表">
|
||||
<a-button type="text" size="small" @click="$emit('action', 'orderedList')" title="有序列表">
|
||||
<template #icon><OrderedListOutlined /></template>
|
||||
</a-button>
|
||||
</a-space>
|
||||
|
|
@ -68,9 +68,8 @@ import {
|
|||
OrderedListOutlined,
|
||||
LinkOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { useEditor } from '../composables/useEditor';
|
||||
|
||||
const { triggerAction } = useEditor();
|
||||
defineEmits(['action']);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="live-editor">
|
||||
<EditorToolbar />
|
||||
<EditorToolbar @action="handleToolbarAction" />
|
||||
<codemirror
|
||||
v-model="code"
|
||||
placeholder="请输入 Markdown 内容..."
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onUnmounted, ref, watch } from 'vue'
|
||||
import { computed, onUnmounted, ref, watch, shallowRef } from 'vue'
|
||||
import { Codemirror } from 'vue-codemirror'
|
||||
import { markdown } from '@codemirror/lang-markdown'
|
||||
import { EditorView } from '@codemirror/view'
|
||||
|
|
@ -44,7 +44,7 @@ const { applyHeading, wrapSelection, prefixLines, insertLink } = useMarkdownActi
|
|||
// 配置 Markdown 扩展
|
||||
const markdownExtension = markdown()
|
||||
|
||||
const editorView = ref(null)
|
||||
const editorView = shallowRef(null)
|
||||
let detachPaste = null
|
||||
let removeActionListener = null
|
||||
|
||||
|
|
@ -267,6 +267,16 @@ const handleReady = (payload) => {
|
|||
if (activeTab.value?.filePath !== props.filePath || !editorView.value) return
|
||||
|
||||
const view = editorView.value
|
||||
executeAction(view, action, payload)
|
||||
})
|
||||
}
|
||||
|
||||
const handleToolbarAction = (action, payload) => {
|
||||
if (!editorView.value) return
|
||||
executeAction(editorView.value, action, payload)
|
||||
}
|
||||
|
||||
const executeAction = (view, action, payload) => {
|
||||
switch (action) {
|
||||
case 'heading': applyHeading(view, payload); break;
|
||||
case 'bold': wrapSelection(view, '**', '**'); break;
|
||||
|
|
@ -278,9 +288,9 @@ const handleReady = (payload) => {
|
|||
case 'orderedList': prefixLines(view, (i) => `${i + 1}. `); break;
|
||||
case 'link': insertLink(view); break;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onUnmounted(() => {
|
||||
if (typeof detachPaste === 'function') detachPaste()
|
||||
if (removeActionListener) removeActionListener()
|
||||
|
|
|
|||
Loading…
Reference in New Issue