给 Vue 页面加个 Markdown 编辑器:ME.js 的接入、图片粘贴与音视频

给 Vue 页面加个 Markdown 编辑器:ME.js 的接入、图片粘贴与音视频

给后台加一个文章编辑框,常见的需求其实没那么复杂:能排版,能贴图,内容最好还能以 Markdown 存下来。

ME.js 做的就是这件事。它不是左边写语法、右边看预览的双栏编辑器,而是在排好版的内容上直接编辑,再把结果序列化成 Markdown。项目同时提供原生 JavaScript、Vue 3 和 React 18 三种接入文件。下面以 Vue 版为主,把接入方式和几个容易踩的点说清楚。12

先说明核对范围:本文对照了演示页和仓库提交 7f25980e99f97c746b86293f1a5bf28de159e41b,并运行了 Vue 版解析器及上传 URL 拼接的代码级测试;不是完整的浏览器兼容性测试。文中配图均为说明示意,不是产品截图。

框架示例已经备好,不用先搭一套工程

仓库的 src 目录里有三个入口:1

页面用什么 加载哪个文件 内容如何绑定
原生 JavaScript me-editor.js ME.init() 创建实例
Vue 3 me-vue.js v-model
React 18 me-react.js value 和 onChange

每个文件已经包含编辑器核心,不需要先加载原生版,再叠加 Vue 或 React 适配层。项目也提供对应的演示页面,可以直接照着改。1

这里的"开箱即用",指的是不用为了试一个编辑框,先准备打包器和脚手架。Vue、React 本身还是要加载。当前 Vue 文件使用全局 Vue 和字符串模板,下面也按这个方式接入,不把它写成一个尚未核实的 npm 包用法。2

把下面的代码保存成 HTML,通过本地静态服务打开,即可开始接入验证。示例固定了编辑器的源码版本,避免 main 分支变化后,文章里的行为跟着变。

html 复制代码
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>ME Vue 编辑器示例</title>
</head>
<body>
  <div id="app">
    <me-editor
      v-model="content"
      :options="editorOptions"
    ></me-editor>
    <h3>当前 Markdown</h3>
    <pre>{{ content }}</pre>
  </div>

  <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/juicy696/markdown-editor@7f25980e99f97c746b86293f1a5bf28de159e41b/src/me-vue.js"></script>
  <script>
    Vue.createApp({
      data() {
        return {
          content: '# 开始写作\n\n这里是一段 **加粗文字**。',
          editorOptions: {
            title: '文章编辑器',
            placeholder: '写点什么......',
            uploadUrl: null,
            showViewCode: true,
            showCopy: true,
            showAudio: true,
            showVideo: true,
            showStatusBar: true,
            maxLength: 0
          }
        };
      }
    }).use(MEVue).mount('#app');
  </script>
</body>
</html>

标题放在 options.title 里。虽然演示文档里也出现了直接传 title 的写法,但当前组件声明的 props 只有 modelValue 和 options,内部导航标题读取的是 opts.title。2

在已有 Vue 工程中接入时,还要留意它当前是全局脚本,不是标准的单文件组件示例。不要直接把上面的代码理解成 import MeEditor from '某个包' 就能用。

图片直接粘贴,后端没准备好也能先写

图片粘贴是这个编辑器很实用的一点。当前 Vue 实现会检查剪贴板里的图片项,再根据 uploadUrl 选择处理方式:2

  • 没有配置上传地址:读取图片,转成 Base64 Data URL 后插入。
  • 配了上传地址:先上传,再把响应里的图片 URL 插入正文。
  • 上传过程抛出错误:提示上传失败,回退到 Base64。

也就是说,试用时可以先不搭图床;正式用到文章后台,再把上传接口接上。

上传接口需要做什么

前端发送的是 POST 请求,正文为 multipart/form-data,图片字段名是 file。后端返回 JSON,其中需要有 url 字段。2

json 复制代码
{
  "url": "https://static.example.com/uploads/example.png"
}

下面是配置形状,域名需要替换成你自己的服务,不是可以直接使用的公共接口:

js 复制代码
editorOptions: {
  title: '文章编辑器',
  uploadUrl: 'https://api.example.com/upload'
}

建议上传地址和响应中的图片地址都使用完整的 HTTPS URL。当前实现遇到相对图片路径时,会用 new URL(uploadUrl).origin 拼接;如果 uploadUrl 也只写成 /upload,这个构造会失败,最后落到 Base64 回退。我对这段函数做了模拟响应测试,确认了这个分支。2

另外,文档列出了 pasteImage: 'auto' | 'base64' | 'upload',但当前 Vue 版的粘贴处理函数并没有读取这个选项,真正决定分支的是有没有 uploadUrl。因此,不能一边配置上传地址,一边指望 pasteImage: 'base64' 强制走内嵌。12

Base64 适合临时记录和小图,不适合在长文章里大量堆图。它把图片内容放进正文,保存、传输和后续编辑都要一起处理这段数据。当前状态栏又是按序列化后的 Markdown 字符串计数,一张 Base64 图片就可能让"字符数"明显上涨。2

如果业务要求"上传失败就不准提交",还需要自己补失败状态和提交校验,不能把默认回退当成上传成功。

仓库里带了一个上传服务

项目提供 server.py,基于 Python 标准库,可以作为本地联调的上传接收端:13

bash 复制代码
python server.py
# 默认端口:1688

python server.py 9000
# 换一个端口

接口是 POST /upload,上传后的文件通过 /uploads/ 路径访问。3

这能省掉验证图片上传时临时写接口的工夫,但它不是拿来直接暴露到公网的生产图床。项目 README 也明确提醒了这一点。正式部署仍要处理鉴权、文件类型和大小校验、访问控制,以及自己的存储策略。1

音频、视频有入口,但保存后要再检查一次

工具栏提供音频和视频插入入口,填入资源 URL 后,编辑区插入浏览器原生的 <audio>、<video> 元素,并带上 controls。这两个按钮分别由 showAudio 和 showVideo 控制。2

它做的是"插入已有媒体地址",不是内置录音、视频剪辑或转码。资源是否能播,也要看地址是否可访问、媒体编码和浏览器支持情况。

序列化时,音视频会以 HTML 标签的形式留在 Markdown 字符串里,例如:2

html 复制代码
<audio src="https://example.com/demo.mp3" controls></audio>
<video src="https://example.com/demo.mp4" controls></video>

这里必须提一个当前版本的限制:能插入,不代表保存后再打开就能原样恢复。

我调用了当前 Vue 版的 MEVue.MdParser.parse(),把上面这样的音视频标签重新传进去,得到的是被转义的 HTML 文本,而不是播放器。这是解析器层面的测试结果,不是对所有浏览器播放效果的判断。2

所以,准备拿它做带媒体的内容后台时,至少要走完一次"插入 → 保存 → 重新打开"。如果要补 HTML 回读,需要同时考虑标签、属性和 URL 的白名单过滤,不建议直接把任意用户内容塞进 innerHTML。

几个写起来顺手的小功能

常规排版之外,当前 Vue 实现里还有这些细节:2

表格可以填行列数插入。 不必先手写一排竖线,再去调整表头。

支持任务列表。 勾选状态可以序列化为 Markdown 的 - [ ] 和 - [x]。

图片可以点选尺寸。 选项包括原始尺寸、100%、75%、50% 和 25%。这里调整的是页面显示尺寸,不是压缩原始图片文件。带尺寸的图片会序列化成 HTML <img>,同样需要注意前面说的 HTML 回读限制。

有查看 Markdown 和复制入口。 写的时候用可视化界面,需要保存或搬运内容时,可以查看底层文本。

有清除格式按钮。 选中内容后,可以去掉格式,不用一项项取消。

工具栏会处理横向空间不足。 放不下的按钮会收进更多菜单。这是源码中实现的溢出处理,不等于已经验证所有手机浏览器的编辑体验。

这些功能放在一起,更适合简单文章、项目说明、内部文档之类的编辑场景。至于协同编辑、修订记录、公式、复杂 Markdown 方言,本文没有验证,也不把它们列成卖点。

配置不用多,但这几个含义要分清

Vue 版常用配置可以先记住这些:2

配置 用途 注意点
title 编辑器顶部标题 放进 options
placeholder 空内容提示 不会成为正文
uploadUrl 粘贴图片上传地址 不配时走 Base64
showViewCode / showCopy 源码查看、复制按钮 默认开启
showAudio / showVideo 音视频按钮 不需要时关闭
showStatusBar 底部字符统计 默认开启
maxLength 超长变红提醒 不是输入拦截,也不是提交校验
iconsMode / iconsLocalPath 图标加载方式 本地图标资源要自己准备

maxLength 很容易看名字就误会。当前逻辑是在计数超过阈值时改变状态栏样式,没有截断输入。业务上需要限制正文长度,仍然要在提交时校验,而且要先决定是统计可见文字,还是包含 Markdown 标记的字符串。2

图标默认通过 Google Fonts 加载 Material Icons。内网或网络受限的环境可以换成本地 CSS:2

js 复制代码
editorOptions: {
  iconsMode: 'local',
  iconsLocalPath: '/assets/material-icons.css'
}

这个配置只是切换资源路径,不会自动下载字体文件。对应 CSS 及其引用的字体,需要自行部署。

还有一个接入细节:当前 options 在组件初始化时合并,没有单独监听后续变化。需要切换整套配置时,要自己处理组件重建,或修改组件以支持配置更新。2

Vue 版先用 v-model,不要直接照搬原生版 API

对于读取和替换内容,Vue 版最直接的入口就是绑定的数据:

js 复制代码
// 读取当前已同步的 Markdown
const markdown = this.content;

// 从接口拿到文章后,替换绑定值
this.content = '# 新文章\n\n正文';

普通输入目前有约 400ms 的防抖同步。接正式保存按钮时,要测试"刚打完字马上保存"的情况,避免保存到尚未更新的值。2

演示文档还列了通过组件 ref 调用 setMarkdown()、getMarkdown()、importFromElement()、download() 的例子。但当前 Vue 组件的方法列表中没有这些方法;原生 JavaScript 版才有对应实现。这里以源码为准,不把文档里的写法直接放进可用示例。24

如果需要程序化导出,原生版提供 Markdown、HTML 和混合格式相关接口;如果用 Vue 版,建议先围绕 v-model 接自己的保存流程,再验证需要的导出格式。4

什么情况下值得用

如果你需要的是一个能很快放进页面的编辑框,要求基本排版、图片粘贴和 Markdown 存储,ME.js 的接入方式值得一看。三个框架入口、已有的演示模板和简单的图片上传约定,省掉了不少起步工作。

但"能开箱跑起来"和"可以不做验证就上线"是两回事。音视频与带样式内容的回读、上传失败后的处理、最后一次输入的保存时机,这几项都应该放进接入检查表。

我的建议是先用一篇真实文章试:放两张图、一张表格,再加一段音频,保存后重新打开。这个流程通过了,再去补上传鉴权和业务校验,比单看工具栏上有多少按钮更有用。

项目与核对来源

相关推荐
专业程序开发源1 小时前
springboot高校学生社团管理系统74810-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
Highcharts.js1 小时前
可视化商用图表库对比,如何选择?
前端·javascript·学习·信息可视化·highcharts·前端可视化
TheITSea2 小时前
JavaScript Web APIs
开发语言·前端·javascript
专业程序开发源2 小时前
springboot生命故事书制作小程序65290-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·mysql·小程序·课程设计
鬓戈2 小时前
Claude Code frontend-design 插件调研 与 Vue 旧系统风格一致性方案
前端·vue.js·人工智能
开开心心就好2 小时前
以图搜图找重复图片,本地工具离线就能用
javascript·智能手机·ffmpeg·c#·ocr·word·音视频
vx_Biye_Design2 小时前
springboot角色扮演服务平台65161-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·spring·课程设计
企业数字化笔记2 小时前
视频局部合成怎么做得自然?掩膜修复、边缘羽化、时序稳定与背景替换
java·javascript·音视频
vx_Biye_Design3 小时前
springboot咖啡厅顾客点单管理系统12080-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express