Appearance
父组件集成
父组件通常负责路由、业务按钮、文件选择器、保存位置、分享反馈和权限状态;MolEditor 负责画布、历史、选区、对象编辑与插件 runtime。
完整宿主工具栏示例
vue
<script setup lang="ts">
import { ref } from 'vue'
import { MolEditor, PRESET_TOOLS, type DocumentSnapshot } from '@shangchien/molio'
import '@shangchien/molio/style.css'
const editorRef = ref<InstanceType<typeof MolEditor> | null>(null)
const fileInputRef = ref<HTMLInputElement | null>(null)
const snapshot = ref<DocumentSnapshot | null>(null)
const shareUrl = ref('')
function openFilePicker() {
fileInputRef.value?.click()
}
async function onOpenFile(event: Event) {
const input = event.target as HTMLInputElement
const file = input.files?.[0]
if (!file || !editorRef.value) return
const nextSnapshot = await editorRef.value.loadDocumentWithWorkflow(file)
if (nextSnapshot)
editorRef.value.restoreDocumentSnapshot(nextSnapshot)
input.value = ''
}
async function onSaveFile() {
const blob = await editorRef.value?.saveDocumentWithWorkflow()
if (!blob) return
downloadBlob(blob, 'project.mpz')
}
async function onShare() {
const shared = await editorRef.value?.shareDocumentWithWorkflow()
shareUrl.value = shared?.url ?? ''
if (shared?.url)
await navigator.clipboard.writeText(shared.url)
}
function downloadBlob(blob: Blob, filename: string) {
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = filename
link.click()
URL.revokeObjectURL(url)
}
</script>
<template>
<div class="host-toolbar">
<button type="button" :disabled="!editorRef?.canUndo" @click="editorRef?.undo()">Undo</button>
<button type="button" :disabled="!editorRef?.canRedo" @click="editorRef?.redo()">Redo</button>
<button type="button" @click="editorRef?.reset()">Reset</button>
<button type="button" @click="openFilePicker">读取文件</button>
<button type="button" @click="editorRef?.addExplicitHydrogens()">加显式氢</button>
<button type="button" @click="editorRef?.removeExplicitHydrogens()">去显式氢</button>
<button type="button" @click="editorRef?.exportStagePng('molio.png')">导出 PNG</button>
<button type="button" @click="editorRef?.exportStageSvg('molio.svg')">导出 SVG</button>
<button type="button" @click="onSaveFile">保存文件</button>
<button type="button" @click="onShare">分享</button>
</div>
<input ref="fileInputRef" hidden type="file" accept=".mpz" @change="onOpenFile">
<MolEditor
ref="editorRef"
v-model:document-snapshot="snapshot"
:options="{ width: 960, height: 640, defaultTool: PRESET_TOOLS.select }"
/>
<a v-if="shareUrl" :href="shareUrl" target="_blank" rel="noreferrer">打开分享链接</a>
</template>方法返回值约定
| 方法 | 返回值 | 说明 |
|---|---|---|
undo() / redo() | boolean | 历史栈有可执行项时返回 true。 |
reset() | void | 清空当前文档,并按 options.viewport.autoFitOnLoad 处理视口。 |
loadDocumentWithWorkflow(file) | Promise<DocumentSnapshot | null> | 需要 persistence workflow;返回快照后由宿主调用 restoreDocumentSnapshot()。 |
saveDocumentWithWorkflow() | Promise<Blob | null> | 需要 persistence workflow;宿主决定下载、上传或自动保存。 |
shareDocumentWithWorkflow() | Promise<{ url?: string, blob?: Blob } | null> | 需要 share workflow;宿主决定复制 URL、二维码或上传 blob。 |
exportStagePng(filename?) / exportStageSvg(filename?) | void | 导出当前画布。 |
addExplicitHydrogens() / removeExplicitHydrogens() | boolean | 有选区时作用于选中分子;无选区时作用于全部分子。 |
宿主自行读取 SMILES / SDF
loadDocumentWithWorkflow() 面向 .mpz 或宿主 persistence 服务。如果文件来自业务接口,父组件可以先使用工具函数解析,再写入编辑器:
ts
import { molOrSdfToRdkitJsons, smilesToRdkitJson } from '@shangchien/molio/utils'
const sdfText = await fetch('/api/molecules.sdf').then(res => res.text())
const sdf = await molOrSdfToRdkitJsons(sdfText)
if (sdf.ok)
editorRef.value?.reload(sdf.data)
const ethanol = await smilesToRdkitJson('CCO')
if (ethanol.ok)
editorRef.value?.importMolecules([ethanol.data])受控快照
v-model:document-snapshot 适合宿主保存草稿、实现外部撤销栈或把文档同步到业务状态。组件会避免把刚刚 emit 出去的同一个快照立刻恢复回来,因此可以安全地接入 Vue ref。