本文将介绍编辑器的应用和随同的某些开发技巧。
该编辑器反对的性能有:根底的md编辑、md语法快捷键、记录保留、暗黑主题、图片上传/复制图片上传/裁剪图片上传、格式化内容、浏览器全屏/屏幕全屏、仅预览模式等性能,静待应用。
具体的编辑器api参考:文档。
- 图片裁剪预览
- 编辑器预览
1. 根本应用
这里演示两种环境三种写法:
1.1 npm装置用法
这种形式反对两种写法,除了.vue
模板写法,还有jsx
语法。
装置
yarn add md-editor-v3
.vue
模板根底应用
<template> <md-editor v-model="text" /> </template> <script lang="ts"> import { defineComponent } from 'vue'; import MdEditor from 'md-editor-v3'; import 'md-editor-v3/lib/style.css'; export default defineComponent({ components: { MdEditor }, data() { return { text: '' }; } }); </script>
jsx
语法根底应用
import { defineComponent, ref } from 'vue';import MdEditor from 'md-editor-v3';import 'md-editor-v3/lib/style.css';export default defineComponent({ name: 'MdEditor', setup() { const text = ref(''); return () => ( <MdEditor modelValue={text.value} onChange={(v: string) => (text.value = v)} /> ); }});
1.2 script标签引入用法
链接可返回https://cdn.jsdelivr.net搜寻md-editor-v3
。
<!--增加款式--><link href="https://cdn.jsdelivr.net/npm/md-editor-v3@1.2.0/lib/style.css" rel="stylesheet" /><!--引入vue3--><script src="https://cdn.jsdelivr.net/npm/vue@3.1.5/dist/vue.global.prod.min.js"></script><!--引入组件--><script src="https://cdn.jsdelivr.net/npm/md-editor-v3@1.2.0/lib/md-editor-v3.umd.js"></script>
注册组件
const App = { data() { return { text: 'Hello Editor!!' }; }};Vue.createApp(App).use(MdEditorV3).mount('#md-editor-v3');
应用组件
<div id="md-editor-v3"> <md-editor-v3 v-model="text" /></div>
2. 渲染内容
该编辑器应用marked
解析md
为html
,没有扩大语法。
通常来讲,编辑内容存储为md
格局,渲染内容时,通过marked
解析为html。
2.1 默认渲染
从1.3.0
版本后,编辑器反对了previewOnly
性能,能够间接应用编辑器预览文章,没有bar、编辑等等。
<template> <md-editor v-model="text" previewOnly /></template><script lang="ts">import { defineComponent } from 'vue';import MdEditor from 'md-editor-v3';import 'md-editor-v3/lib/style.css';export default defineComponent({ components: { MdEditor }, data() { return { text: '## 我只会显示预览内容' }; }});</script>
2.2 被动解析演示
这种形式用于保留md
,而后自行解析md
内容。
import marked from 'marked';// 代码高亮import hljs from 'highlight.js';// 自选代码高亮款式import 'highlight.js/scss/atom-one-dark.scss';// 用于记录题目数,依据业务代替let count = 0;// 记录题目内容const headstemp = [];// marked设置const rendererMD = new marked.Renderer();// 调整题目内容rendererMD.heading = (text, level) => { headstemp.push({ text, level }); count++; return `<h${level} id="heading-${count}"><span class="h-text">${text}</span></h${level}>`;};// 设置图片内容,对立显示一张缓存图,用于懒加载~rendererMD.image = (href, _, text) => `<img data-src="${href}" src="/cos/2020/1211175603.png" alt="${text}" >`;marked.setOptions({ highlight(code) { return hljs.highlightAuto(code).value }, renderer: rendererMD});// 这里的html就是插入到页面的元素文本了const html = marked('## md内容');
2.3 题目导航实现
下面的例子headstemp
记录了解析过程中的所有题目,作用是借助UI库的组件Anchor
,构建一个题目导航。
上面演示一个基于ant-design-vue
的版本,如果你应用的UI库是相似的锚点组件,那么代码将只须要小改变即可。代码应用jsx
语法,vue
模板语法请自行拆散代码~
Recursive.tsx 导航中的链接组件
import { Anchor } from 'ant-design-vue';import { defineComponent, PropType } from 'vue';const { Link } = Anchor;export interface Head { text: string; level: number;}export interface TocItem extends Head { anchor: string; children?: Array<TocItem>;}const Recursive = defineComponent({ props: { tocItem: { type: Object as PropType<TocItem>, default: () => [] } }, setup({ tocItem }) { return ( <Link href={`#${tocItem.anchor}`} title={tocItem.text}> {tocItem.children && tocItem.children.map((item) => <Recursive key={item.anchor} tocItem={item} />)} </Link> ); }});export default Recursive;
Topicfy.tsx 用于生成整个导航内容
import { Anchor } from 'ant-design-vue';import { computed, defineComponent, PropType, ref, watch } from 'vue';import Recursive, { Head, TocItem } from './Recursive';const Topicfy = defineComponent({ props: { // 解析失去的题目列表 heads: { type: Array as PropType<Array<Head>> } }, setup(props) { const topics = computed(() => { const tocItems: TocItem[] = []; // 题目计数器 let count = 0; const add = (text: string, level: number) => { count++; const item = { anchor: `heading-${count}`, level, text }; if (tocItems.length === 0) { // 第一个 item 间接 push tocItems.push(item); } else { let lastItem = tocItems[tocItems.length - 1]; // 最初一个 item if (item.level > lastItem.level) { // item 是 lastItem 的 children for (let i = lastItem.level + 1; i <= 6; i++) { const { children } = lastItem; if (!children) { // 如果 children 不存在 lastItem.children = [item]; break; } // 重置 lastItem 为 children 的最初一个 item lastItem = children[children.length - 1]; if (item.level <= lastItem.level) { // item level 小于或等于 lastItem level 都视为与 children 同级 children.push(item); break; } } } else { // 置于最顶级 tocItems.push(item); } } }; props.heads?.forEach((item) => { add(item.text, item.level); }); return tocItems; }); return () => ( <Anchor affix={false} showInkInFixed={true}> {topics.value.map((item) => ( <Recursive key={item.anchor} tocItem={item} /> ))} </Anchor> ); }});export default Topicfy;
该组件是19年参考了网络上的实现实现的,非自己齐全原创,react版本参考Topicfy
2.4 获取html代码
编辑器思考到了可能后端不存储md
格局的文本,而是html
内容,所以提供了onHtmlChanged
办法,用于编辑内容变动后,marked
编译了内容的回调,入参即是html
内容。
<template> <md-editor v-model="text" @onHtmlChanged="saveHtml" /></template><script lang="ts">import { defineComponent } from 'vue';import MdEditor from 'md-editor-v3';import 'md-editor-v3/lib/style.css';export default defineComponent({ components: { MdEditor }, data() { return { text: '' }; }, methods: { saveHtml(h: string) { console.log(h) }}});</script>
jsx
语法雷同。
3. 编辑器的性能演示
3.1 扩大库链接
编辑器扩大内容大多应用了cdn
,思考了无外网状况,反对了内网链接扩大,演示(假如内部库都在根目录下):
<template> <md-editor v-model="text" highlightJs="/highlight.min.js" highlightCss="/atom-one-dark.min.css" prettierCDN="/standalone.js" prettierMDCDN="/parser-markdown.js" cropperJs="/cropper.min.js" cropperCss="/cropper.min.css" /></template><script lang="ts">import { defineComponent } from 'vue';import MdEditor from 'md-editor-v3';import 'md-editor-v3/lib/style.css';export default defineComponent({ components: { MdEditor }, data() { return { text: '' }; }});</script>
v1.2.0版本目前反对上述链接,图标链接将在后续补丁中增加。
3.2 工具栏自定义
默认的全副工具栏,并且每个性能都绑定了快捷键,如果须要选择性显示工具栏,提供了两个api:toolbars
和toolbarsExclude
,前者显示数组中的全副,后者屏蔽数组中的全副,后者的权重更大。上面是个参考:
案例不显示github
按钮
<template> <md-editor v-model="text" :toolbars="toobars" /> <md-editor v-model="text" :toolbarsExclude="toolbarsExclude" /></template><script lang="ts">import { defineComponent } from 'vue';import MdEditor from 'md-editor-v3';import 'md-editor-v3/lib/style.css';export default defineComponent({ components: { MdEditor }, data() { return { text: '', toobars: ['bold', 'underline', 'italic', 'strikeThrough', 'sub','sup','quote','unorderedList', 'orderedList', 'codeRow', 'code', 'link', 'image', 'table', 'revoke', 'next', 'save', 'pageFullscreen', 'fullscreen', 'preview', 'htmlPreview'], toolbarsExclude: ['github'] }; }});</script>
3.3 扩大语言
编辑器默认内置了中文和英文,并且两者都能够通过扩大api笼罩,该性能次要用来设置内容提醒,比方弹窗中的题目等。
扩大一门语言,咱们取名为zh-NB
<template> <md-editor v-model="text" :language="language" :languageUserDefined="languageUserDefined" /></template><script lang="ts">import { defineComponent } from 'vue';import MdEditor, { StaticTextDefaultValue } from 'md-editor-v3';import 'md-editor-v3/lib/style.css';const languageUserDefined: { 'zh-NB': StaticTextDefaultValue } = { 'zh-NB': { toolbarTips: { bold: '加粗', underline: '下划线', italic: '斜体', strikeThrough: '删除线', title: '题目', sub: '下标', sup: '上标', quote: '援用', unorderedList: '无序列表', orderedList: '有序列表', codeRow: '行内代码', code: '块级代码', link: '链接', image: '图片', table: '表格', revoke: '后退', next: '后退', save: '保留', prettier: '丑化', pageFullscreen: '浏览器全屏', fullscreen: '屏幕全屏', preview: '预览', htmlPreview: 'html代码预览', github: '源码地址' }, titleItem: { h1: '一级题目', h2: '二级题目', h3: '三级题目', h4: '四级题目', h5: '五级题目', h6: '六级题目' }, linkModalTips: { title: '增加', descLable: '链接形容:', descLablePlaceHolder: '请输出形容...', urlLable: '链接地址:', UrlLablePlaceHolder: '请输出链接...', buttonOK: '确定', buttonUpload: '上传' }, // v1.2.0新增 clipModalTips: { title: '裁剪图片上传', buttonUpload: '上传' }, // v1.1.4新增 copyCode: { text: '复制代码', tips: '已复制' } }};export default defineComponent({ components: { MdEditor }, data() { return { text: '', language: "zh-NB", languageUserDefined }; }});</script>
如果key = 'zh-CN',就能够实现中文笼罩,顺次类推。
3.4 主题切换
这一块绝对比较简单了,内置了暗黑主题和默认主题,通过theme
api切换,demo如下:
<template> <md-editor v-model="text" :theme="theme" /></template><script lang="ts">import { defineComponent } from 'vue';import MdEditor from 'md-editor-v3';import 'md-editor-v3/lib/style.css';export default defineComponent({ components: { MdEditor }, data() { return { text: '', theme: 'dark' }; }});</script>
4. 结尾
更多的更新请关注:[md-editor-v3]()