Quill 编辑器自定义视频模块:将 iframe 替换为 video 标签
前言
在使用 Quill 富文本编辑器时,默认的视频模块会使用 <iframe> 标签来嵌入视频。这种方式在某些场景下存在一些问题,特别是对于竖屏视频,iframe 可能无法正确显示视频的宽高比。本文将介绍如何自定义 Quill 的视频模块,将默认的 iframe 标签替换为 <video> 标签,从而更好地控制视频的显示效果。
问题背景
Quill 编辑器默认的视频模块存在以下问题:
- 竖屏视频显示问题:使用 iframe 嵌入视频时,竖屏视频可能无法正确显示宽高比
- 控制能力有限:iframe 标签对视频的控制能力较弱,无法直接使用 HTML5 的原生视频控制功能
- 样式定制困难:iframe 的样式定制相对复杂,不如 video 标签灵活
解决方案
通过创建自定义的 Video Blot(Quill 中的内容块类型),我们可以完全控制视频标签的渲染方式,使用原生的 <video> 标签替代默认的 <iframe> 标签。
实现步骤
步骤一:创建自定义视频模块
在 Vue 项目的 src/components/Editor 目录下创建 quill 文件夹,然后创建 video.js 文件:
javascript
import Quill from "quill";
const BlockEmbed = Quill.import("blots/block/embed");
class Video extends BlockEmbed {
static create(value) {
let node = super.create();
// 处理字符串 URL 或对象格式 {url: "..."}
const url =
typeof value === "string" ? value : value && value.url ? value.url : "";
node.setAttribute("src", url);
node.setAttribute("controls", "controls");
node.setAttribute("width", "100%");
node.setAttribute("style", "height: auto;");
return node;
}
static value(node) {
return {
url: node.getAttribute("src"),
};
}
}
Video.blotName = "video";
Video.tagName = "video";
export default Video;
代码说明:
BlockEmbed:Quill 提供的块级嵌入基类,用于创建自定义的嵌入内容create(value):创建视频节点的方法- 处理两种输入格式:字符串 URL 或对象格式
{url: "..."} - 设置视频属性:
src、controls、width等 height: auto确保视频保持原始宽高比
- 处理两种输入格式:字符串 URL 或对象格式
value(node):从 DOM 节点提取视频 URL 的方法blotName:Blot 的名称,必须与 Quill 的视频模块名称一致tagName:使用的 HTML 标签名称,这里使用video
步骤二:在编辑器组件中注册自定义模块
在 src/components/Editor/index.vue 文件中引入并注册自定义视频模块:
vue
<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import Video from "./quill/video";
// 注册自定义视频模块
Quill.register(Video, true);
export default {
name: "Editor",
// ... 其他代码
};
</script>
关键点:
- 必须在创建 Quill 实例之前注册自定义模块
Quill.register(Video, true)中的第二个参数true表示如果已存在同名模块则强制覆盖
步骤三:确保工具栏包含视频按钮
在 Quill 的配置中,确保工具栏包含视频按钮:
javascript
modules: {
toolbar: [
// ... 其他工具栏按钮
["link", "image", "video"] // 链接、图片、视频
]
}
完整代码示例
video.js 完整代码
javascript
import Quill from "quill";
const BlockEmbed = Quill.import("blots/block/embed");
class Video extends BlockEmbed {
static create(value) {
let node = super.create();
// 处理字符串 URL 或对象格式 {url: "..."}
const url =
typeof value === "string" ? value : value && value.url ? value.url : "";
node.setAttribute("src", url);
node.setAttribute("controls", "controls");
node.setAttribute("width", "100%");
node.setAttribute("style", "height: auto;");
return node;
}
static value(node) {
return {
url: node.getAttribute("src"),
};
}
}
Video.blotName = "video";
Video.tagName = "video";
export default Video;
Editor/index.vue 关键部分
vue
<template>
<div>
<div class="editor" ref="editor" :style="styles"></div>
</div>
</template>
<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { getToken } from "@/utils/auth";
import Video from "./quill/video";
// 注册自定义视频模块
Quill.register(Video, true);
export default {
name: "Editor",
data() {
return {
Quill: null,
options: {
theme: "snow",
modules: {
toolbar: [
["bold", "italic", "underline", "strike"],
["blockquote", "code-block"],
[{ list: "ordered" }, { list: "bullet" }],
[{ indent: "-1" }, { indent: "+1" }],
[{ size: ["small", false, "large", "huge"] }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }],
[{ align: [] }],
["clean"],
["link", "image", "video"] // 包含视频按钮
],
},
placeholder: "请输入内容",
},
};
},
mounted() {
this.init();
},
methods: {
init() {
const editor = this.$refs.editor;
this.Quill = new Quill(editor, this.options);
},
},
};
</script>
效果对比
修改前(默认 iframe)
html
<iframe src="video-url" frameborder="0" allowfullscreen="true"></iframe>
修改后(自定义 video)
html
<video src="video-url" controls="controls" width="100%" style="height: auto;"></video>
优势
使用自定义 video 标签后,获得了以下优势:
- 更好的宽高比控制 :
height: auto确保视频保持原始宽高比,竖屏视频可以正确显示 - 原生视频控制 :使用 HTML5 原生的
controls属性,提供更好的用户体验 - 样式定制灵活:可以直接通过 CSS 定制视频样式
- 性能优化:video 标签比 iframe 更轻量,性能更好
注意事项
- URL 格式处理:代码中已经处理了字符串和对象两种格式的 URL,确保兼容性
- 注册时机:必须在创建 Quill 实例之前注册自定义模块
- 浏览器兼容性:确保目标浏览器支持 HTML5 video 标签
- 视频格式:video 标签支持的视频格式取决于浏览器,建议使用 MP4、WebM 等通用格式
常见问题
Q: 为什么视频 URL 显示为 undefined?
A: 这是因为 Quill 传递的可能是字符串格式的 URL,而不是对象格式。代码中已经处理了这种情况:
javascript
const url =
typeof value === "string" ? value : value && value.url ? value.url : "";
Q: 如何自定义视频样式?
A: 可以在 CSS 中直接针对 video 标签添加样式:
css
.editor video {
max-width: 100%;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
Q: 如何添加更多视频属性?
A: 在 create 方法中可以添加更多属性,例如:
javascript
node.setAttribute("preload", "metadata");
node.setAttribute("poster", "poster-image-url");
node.setAttribute("muted", "muted");
总结
通过自定义 Quill 的视频模块,我们成功地将默认的 iframe 标签替换为 video 标签,解决了竖屏视频显示问题,并获得了更好的控制能力和用户体验。这个方案简单易用,只需要创建自定义 Blot 并注册即可,无需修改 Quill 的核心代码。