基于 Vue 组件化方案定制 Cherry-Markdown 视频渲染样式
背景与目标
在 Markdown 文档渲染场景中,浏览器原生的 video 标签往往无法满足特定的交互需求或统一的设计规范。为了提升内容展示的视觉效果与功能丰富度,我们需要在 cherry-markdown 框架内实现自定义的视频播放容器,并能够复用 Vue 生态中的组件库能力。
技术调研与方案确定
深入分析 cherry-markdown 的源码及社区反馈后,发现其引擎配置提供了针对图片及媒体资源的扩展钩子。虽然存在针对原生视频的实现案例,但若要深度集成第三方的 UI 组件库(如 PrimeVue)或封装复杂的业务逻辑,直接返回静态 HTML 字符串不足以支撑组件的生命周期管理。
核心实现:Vue 组件静态化渲染
为了解决钩子函数仅支持返回 HTML 字符串的限制,可以采用"临时挂载"策略。即创建一个不可见的 DOM 节点,将 Vue 组件实例挂载其上,待渲染完成后提取生成的 DOM 结构,最后销毁实例。这样既能利用 Vue 的模板语法和响应式数据,又能兼容只接受字符串的渲染接口。
以下是封装好的工具函数,用于将 Vue 组件转换为可插入的 HTML 片段:
/**
* 将 Vue 组件同步渲染为 HTML 字符串
* @param {Object} Component - Vue 组件定义
* @param {Object} options - 传递给组件的属性对象
*/
const serializeVueComponent = (Component, options = {}) => {
// 构建临时的挂载容器
const scratchPad = document.createElement('div');
try {
// 初始化 Vue 应用实例
const vueApp = createApp(Component, options);
// 按需注入全局插件库,确保样式与功能正常
vueApp.use(PrimeVue, { ripple: true });
// 执行挂载操作
vueApp.mount(scratchPad);
// 获取编译后的内部 HTML
let markup = scratchPad.innerHTML;
// 清理 DOM 残留
scratchPad.innerHTML = '';
return markup;
} catch (error) {
console.error('组件序列化失败:', error);
return '';
}
};
配置整合与应用
在 cherry-markdown 的初始化配置中,拦截视频类型的资源处理逻辑。当检测到类型为 video 时,不再使用默认包裹器,而是调用上述工具函数生成自定义组件的静态 HTML。
import { createMarkdownEngine } from 'cherry-markdown';
import MyVideoPlayer from './components/MyVideoPlayer.vue';
const engineConfig = {
engine: {
syntax: {
image: {
videoWrapper: (resourceLink, resourceType, fallbackHandler) => {
// 仅对视频资源进行自定义处理
if (resourceType !== 'video') {
return fallbackHandler(resourceLink, resourceType);
}
// 传递视频地址到 Vue 组件并获取渲染结果
const customMarkup = serializeVueComponent(MyVideoPlayer, { srcUrl: resourceLink });
return customMarkup;
},
},
},
},
};
通过上述方式,视频资源将被替换为由 Vue 组件控制的播放界面,支持动态加载皮肤、统计埋点等高级功能。