vue.js 3: markmap using typescript
在项目目录文件下,通过cmd运行下述指令。
npm create vue@latest
cd vue-projectnpm installnpm run format
npm run dev或
npm init vue@latest
cd vue-prjectnpm run build --打包项目创建项目没有node_modules
npm init -y
npm install vue-routernpm install markmap-lib
npm install markmap-render
npm install markmap-view
npm install markmap-cli
npm install markmap-toolbar
npm install coc-markmap
npm i markmap-autoloade
项目结构:
/** @creater: geovindu* @since: 2025-06-24 22:22:55* @LastAuthor: geovindu* @lastTime: 2025-06-24 22:23:29* @文件相对于项目的路径: \jsstudy\markmapdemo\src\views\markmap.ts* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.*/
import { loadJS, loadCSS } from 'markmap-common';
import { Transformer } from 'markmap-lib';
import * as markmap from 'markmap-view';// 定义类型
type LoadJS = (scripts: string[],options: { getMarkmap: () => typeof markmap }
) => Promise<void>;type LoadCSS = (styles: string[]) => void;// 创建转换器实例
export const transformer = new Transformer();
const { scripts, styles } = transformer.getAssets();// 加载资源
const loadJSWithType: LoadJS = (scripts, options) => {return loadJS(scripts, options);
};const loadCSSWithType: LoadCSS = (styles) => {loadCSS(styles);
};loadCSSWithType(styles);
loadJSWithType(scripts, { getMarkmap: () => markmap });
<!--* @creater: geovindu* @since: 2025-06-24 22:24:23* @LastAuthor: geovindu* @lastTime: 2025-06-24 22:39:38* @文件相对于项目的路径: \jsstudy\markmapdemo\src\views\VueComposition.vue* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
-->
<template><div class="flex-1"><textarea class="w-full h-full border border-gray-400" v-model="value" /></div><svg class="flex-1" ref="svgRef" /></template><script lang="ts" setup>import { ref, onMounted, onUpdated } from 'vue';import { Markmap } from 'markmap-view';import { transformer } from './markmap';// 定义类型type MarkmapInstance = Markmap;const initValue = `# 中国行政区划
## 北京市
### 市辖区
#### 东城区
##### 五道口街道
###### 教苑社区
- 林海花园
- 江海花园
- 学清苑小区
## 江西省
### 吉安市
#### 永丰县
##### 沿陂镇
###### 涂家村委
- 涂家村
- 艾家村
- 黄家村
## 广东省
### 深圳市
#### 罗湖区
##### 东晓街道
###### 兰心社区
- 江海花园
- 江心花园
- 兰亭国际
###### 田心社区
- 田心村
- 东晓花园
- 鹿鸣园
##### 桂园街道
###### 大塘龙社区
- 大塘龙小区
- 万科桂苑
- 天地大厦`;const svgRef = ref<SVGSVGElement | null>(null);const value = ref<string>(initValue);let mm: MarkmapInstance | null = null;const update = async () => {if (!mm || !svgRef.value) return;try {const { root } = transformer.transform(value.value);await mm.setData(root);mm.fit();} catch (error) {console.error('更新Markmap失败:', error);}};onMounted(() => {if (svgRef.value) {mm = Markmap.create(svgRef.value);update();}});onUpdated(update);</script><style scoped>textarea {font-family: monospace;font-size: 14px;}</style>
<!--* @creater: geovindu* @since: 2025-06-24 22:23:43* @LastAuthor: geovindu* @lastTime: 2025-06-24 22:37:14* @文件相对于项目的路径: \jsstudy\markmapdemo\src\views\VueLegacy.vue* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
-->
<template><div class="flex flex-col h-screen"><div class="flex-1 flex"><textareaclass="w-full h-full border border-gray-400 p-2"v-model="value"placeholder="输入 Markdown 内容..."/><svg ref="svgRef" class="w-full h-full border border-gray-400" /></div></div>
</template><script lang="ts" setup>
import { ref, onMounted, onUpdated, watch } from 'vue';
import { Markmap } from 'markmap-view';
import { transformer } from './markmap';// 定义类型
type MarkmapInstance = Markmap;// 初始值和状态
const initValue = `# 中国行政区划
## 北京市
### 市辖区
#### 东城区
##### 五道口街道
###### 教苑社区
- 林海花园
- 江海花园
- 学清苑小区
## 江西省
### 吉安市
#### 永丰县
##### 沿陂镇
###### 涂家村委
- 涂家村
- 艾家村
- 黄家村
## 广东省
### 深圳市
#### 罗湖区
##### 东晓街道
###### 兰心社区
- 江海花园
- 江心花园
- 兰亭国际
###### 田心社区
- 田心村
- 东晓花园
- 鹿鸣园
##### 桂园街道
###### 大塘龙社区
- 大塘龙小区
- 万科桂苑
- 天地大厦
`;const value = ref(initValue);
const svgRef = ref<SVGSVGElement | null>(null);
let mm: MarkmapInstance | null = null;// 更新 Markmap
const update = async () => {if (!mm || !svgRef.value || !value.value) return;try {const { root } = transformer.transform(value.value);await mm.setData(root);mm.fit();} catch (err) {console.error('更新 Markmap 失败:', err);}
};// 初始化 Markmap
onMounted(() => {if (svgRef.value) {mm = Markmap.create(svgRef.value);update();}
});// 监听值变化并更新 Markmap
watch(value, update);// 组件更新后调整 Markmap
onUpdated(() => {if (mm && svgRef.value) {mm.fit();}
});
</script><style scoped>
textarea {font-family: monospace;font-size: 14px;resize: none;
}
</style>
<!--* @creater: geovindu* @since: 2025-06-24 22:24:23* @LastAuthor: geovindu* @lastTime: 2025-06-24 22:43:26* @文件相对于项目的路径: \jsstudy\markmapdemo\src\views\displayview.vue* @message: geovindu* @IDE: vscode
*npm install markmap-lib
*npm install markmap-render
*npm install markmap-view
*npm install markmap-cli
*npm install markmap-toolbar
*npm install coc-markmap
* npm i markmap-autoloade* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
-->
<template><div class="flex flex-col h-screen p-2"><select class="border border-gray-400" v-model="type"><option value="composition">Composition API</option><option value="legacy">Legacy</option></select><component :is="currentComponent" class="flex-1" /></div>
</template><script lang="ts" setup>
import { ref, computed } from 'vue';
import VueComposition from './VueComposition.vue';
import VueLegacy from './VueLegacy.vue';// 定义类型
type ComponentType = 'composition' | 'legacy';const type = ref<ComponentType>('composition');
const currentComponent = computed(() => {return {composition: VueComposition,legacy: VueLegacy,}[type.value];
});
</script><style scoped>
@import url('https://cdn.jsdelivr.net/npm/tailwindcss@2.2.0/dist/tailwind.min.css');select {padding: 0.5rem;font-size: 1rem;margin-bottom: 0.5rem;
}
</style>