vue.js 3: markmap using typescript

发布于:2025-06-29 ⋅ 阅读:(18) ⋅ 点赞:(0)
在项目目录文件下,通过cmd运行下述指令。
npm create vue@latest
cd vue-project
  
  npm install
 npm run format
npm run dev
  
或
npm init vue@latest
cd vue-prject
  
npm run build --打包项目
 
创建项目没有node_modules
npm init -y
npm install vue-router
 
 
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

项目结构:

/*
 * @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">
      <textarea
        class="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>


网站公告

今日签到

点亮在社区的每一天
去签到