前言

上一篇是修改官方的图片上传行为,这次是修改官方视频按钮默认行为,你会发现官方的视频默认行为,总是采用iframe的形式,如果我们希望是原生video元素,就没办法了,于是就有了本篇教程。

这次自定义和图片就略有不同了,我们不能直接这么插入:

editor.insertEmbed(range.index, 'video', src, Quill.sources.USER);

如果采用这种方式,会导致和官方的行为一致,变成插入的是iframe元素了。

为此,我们需要了解一个新知识:Blot

官方文档对于Blot的介绍很少,我们可以理解是一种行为扩展的方式,可以对用户输入的内容进行转换,比如格式化文本,加粗,包括本次的插入video元素,其实都是一种blot,官方通过register方法,将行为扩展进行注册,从而实现功能扩展。

官方其实预设了一些Blot,我们可以基于这些进行扩展:

  1. Text Blot(文本)

    • 表示普通的文本内容,是最基本的Blot类型。
  2. Block Blot(块)

    • 表示一个块级元素,如段落、标题等。它可以包含多个Text Blot。
  3. Inline Blot(内联)

    • 表示内联元素,如加粗、斜体、链接等。它可以包含多个Text Blot。
  4. Container Blot(容器)

    • 表示一个容器元素,可以包含其他的Blot类型。常见的容器Blot有List(列表)和Table(表格)。

除了这些基本的Blot类型,Quill还提供了一些特殊的Blot类型,用于处理特定的功能和样式,例如:

  1. Embed Blot(嵌入)

    • 表示嵌入式内容,如图片、视频等。Embed Blot可以包含其他的Blot类型,用于表示嵌入内容的各个部分。

扩展视频,我们通过Block Blot就行了,blot有一些预设静态属性,因为它本身是一个class,其中blotNametagName都是必填的,className可写可不写,写了他就是你配置的tagName元素的类名。

教程

先创建一个用于视频的blot,新建videoEmbed.ts文件,内容如下:

import Quill from 'quill';

const blockEmbed = Quill.import('blots/block/embed');

class VideoEmbed extends blockEmbed {
    static blotName = 'VideoEmbed';
    static tagName = 'video';

    static create(url: string) {
        const node = super.create();
        node.setAttribute('src', url);
        node.setAttribute('controls', '');
        node.setAttribute('controlslist', 'nodownload noremoteplayback noplaybackrate');
        node.setAttribute('disablepictureinpicture', '');
        return node;
    }

    static value(node: any) {
        return node.getAttribute('src');
    }
}

export default VideoEmbed;

可以看到创建了一个node节点,然后设置了一些video的属性,具体的意义可以问ai,配置完毕后导出。

下面就是进行注册,必须是通过import引入的Quill注册,官方要求全局,所以不能通过实例的方式注册。

import Quill from 'quill';
import 'quill/dist/quill.snow.css';
import VideoEmbed from './blot/videoEmbed';
Quill.register(VideoEmbed);

现在我们就可以开始自定义视频上传了。

<!-- 视频 -->
<input class="quill-editor-input-file" ref="quillEditorInputVideoRef" type="file" accept="video/*" @change="onFileVideoChange" />
const quillEditorInputVideoRef = ref<HTMLInputElement>();

let editor: Quill;
const editorOptions: QuillOptionsStatic = {
    theme: 'snow',
    modules: {
        toolbar: {
            container: '#quill-edit-toolbar',
            handlers: {
                video: () => {
                    quillEditorInputVideoRef.value ? .click();
                },
            },
        },
    },
    bounds: '.quill-editor-wrapper',
};
/** 文件上传loading */
const uploadLoading = ref(false);


/** 视频change事件 */
function onFileVideoChange(event: Event) {
    const files = (event.target as HTMLInputElement).files!;
    let file: File | null = null;
    if (files.length <= 0) {
        file = null;
        return;
    }
    file = files[0]; // 只取第一个文件
    if (!file) return;
    uploadLoading.value = true;
    uploadApi(file)
        .then((src) => {
            const range = editor.getSelection(true);
            editor.insertText(range.index, '\n', Quill.sources.USER);
            editor.insertEmbed(range.index + 1, 'VideoEmbed', src, Quill.sources.USER);
        })
        .catch((error) => {
            ElMessage.error(`上传视频失败`);
            console.error('上传视频失败', error);
        })
        .finally(() => {
            uploadLoading.value = false;
            quillEditorInputVideoRef.value!.value = ''; // 清空input file
        });
}

/** 上传文件api */
function uploadApi(file: File): Promise < string > {
    return new Promise((resolve, reject) => {
        const fromData = new FormData();
        fromData.append('file', file);
        uploadFile(fromData)
            .then((response: unknown) => {
                const {
                    data
                } = response as ResponseInterface<string> ;
                return resolve(data);
            })
            .catch((err) => {
                return reject(err);
            });
    });
}



//初始化编辑器
nextTick(() => {
    editor = new Quill(quillEditorRef.value!, editorOptions);
});

container: '#quill-edit-toolbar'表示使用html中指定id的容器,具体可以看下一篇自定义工具栏的文章。

其实重点就是这三句代码:

const range = editor.getSelection(true);
editor.insertText(range.index, '\n', Quill.sources.USER);
editor.insertEmbed(range.index + 1, 'VideoEmbed', src, Quill.sources.USER);

先获取用户的光标位置,然后插入一个换行符,然后在length+1的地方,插入自定义的blot类型,这个内容对应blotName静态属性,

至此基本完成,有过有其他需求,可以自己调整。

分类: vue 项目实战 标签: vuequill富文本编辑器视频上传video

评论

暂无评论数据

暂无评论数据

目录