vue3中 v-md-editor 编辑器的基本使用分享
- 安装 (2.3.15以上)
# npm
npm install @kangc/v-md-editor -S
# yarn
yarn add @kangc/v-md-editor@next
- 全局引用(main.js)
import VueMarkdownEditor from '@kangc/v-md-editor';
import '@kangc/v-md-editor/lib/style/base-editor.css';
import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js';
import '@kangc/v-md-editor/lib/theme/style/vuepress.css';
import Prism from 'prismjs';
// 这是预览时引用的
import VMdPreview from '@kangc/v-md-editor/lib/preview';
import '@kangc/v-md-editor/lib/style/preview.css';
// 引入你所使用的主题 此处以 github 主题为例
import githubTheme from '@kangc/v-md-editor/lib/theme/github';
import '@kangc/v-md-editor/lib/theme/style/github.css';
// highlightjs
import hljs from 'highlight.js';
//预览的主题
VMdPreview.use(githubTheme, {
Hljs: hljs,
});
//编辑器的主题
VueMarkdownEditor.use(vuepressTheme, {
Prism,
});
//注册
app.use(VMdPreview);
app.use(VueMarkdownEditor);
- 使用 (编辑器)
<v-md-editor
v-model="form.artContent" //绑定的值
:autofocus="true" //自动选中
height="400px" //高(必须)
width="100%" //宽
ref="editor"
:left-toolbar="leftBar" //左侧工具
:right-toolbar="rightBar" //右侧工具
:disabled-menus="[]" //禁用菜单
@upload-image="handleUploadImage" //上传图片的事件
></v-md-editor>
import { defineComponent, onMounted, reactive, ref, toRefs } from 'vue';
export default defineComponent({
setup() {
//左侧工具栏
const leftBar = ref('undo redo clear h bold italic strikethrough quote ul ol table hr link image code');
//右侧工具栏
const rightBar = ref('preview sync-scroll fullscreen');
//Alt + a 实现上传图片
const handleUploadImage = async (event, insertImage, files) => {
// 拿到 files 之后上传到文件服务器,然后向编辑框中插入对应的内容
const formData = new FormData();
formData.append('file', files[0]);
//你自己的上传文件接口
let res = await FileApi.commonUpload('N', formData);
insertImage({
//state.filePreviewUrl 是我本地的预览接口 你可以换成自己的也可以用上传接口给你反的url
url: state.filePreviewUrl + res.data.fileId,
desc: res.data.fileOriginName
});
};
return { leftBar, rightBar, handleUploadImage }
}
})
- 实现的效果
- 预览操作
//预览
<v-md-preview :text="text" ref="preview" @image-click="imgClick" id="preview"></v-md-preview>
//锚点跳转
<div class="navigation">
<div class="navigation-content" id="permiss">
<div v-for="(anchor, index) in titles" :key="index + 'art'" :style="{ padding: `10px 0 10px ${anchor.indent * 10}px` }">
<a style="cursor: pointer; color: black; margin-left: 20px" @click="handleAnchorClick(anchor, index, anchor.indent)">{{
anchor.title
}}</a>
</div>
</div>
</div>
import { defineComponent, onMounted, reactive, ref, toRefs } from 'vue';
export default defineComponent({
setup() {
//值
const text = ref(null);
// 预览组件的引用
const preview = ref(null);
//锚点数组
const titles = ref([]);
//图片点击
const imgClick = (url, index) => {
console.log(url, index);
};
//获取锚点数组 获取完接口后调用
const getTitle = () => {
nextTick(() => {
//获取所有的标题
const anchors = preview.value.$el.querySelectorAll('h1,h2,h3,h4,h5,h6');
const titles = Array.from(anchors).filter(title => !!title.innerText.trim());
if (!titles.length) {
titles.value = [];
return;
}
const hTags = Array.from(new Set(titles.map(title => title.tagName))).sort();
//给每一个加样式
titles.value = titles.map(el => ({
title: el.innerText,
lineIndex: el.getAttribute('data-v-md-line'),
indent: hTags.indexOf(el.tagName)
}));
nextTick(() => {
//改变样式
let arr = document.getElementById('permiss').getElementsByTagName('a');
let div = document.getElementById('permiss').getElementsByTagName('div');
for (let i = 0; i < arr.length; i++) {
if (i == 0) {
arr[i].style.color = 'var(--primary-color)';
arr[i].style.marginLeft = '20px';
div[i].style.borderLeft = '1px solid var(--primary-color)';
div[i].style.padding = `10px 0 10px ${data.titles[0].indent * 10}px`;
} else {
arr[i].style.color = 'black';
div[i].style.borderLeft = '1px solid #eee';
}
}
});
});
};
return { text, imgClick,titles }
}
})
6.预览的效果图
- 官网分享
https://ckang1229.gitee.io/vue-markdown-editor/zh/question.html#%E5%9C%A8-vite-%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%8A%A5%E9%94%99-%E6%97%A0%E6%B3%95%E6%AD%A3%E5%B8%B8%E8%BF%90%E8%A1%8C