基于 Vue2+Quill 的富文本編輯器全方案:功能實現與樣式優化

在 Web 開發中,富文本編輯器是內容管理系統、博客平臺等應用的核心組件。本文將詳細介紹如何基于 Vue 和 Quill
構建一個功能完善、樣式精美的富文本編輯器,重點解決字體字號選項冗長、樣式不美觀及功能完整性問題,提供可直接部署使用的完整方案。

一、方案概述

本方案基于 Vue 2.x 和 Quill 編輯器,實現了以下核心功能:

  • 完整的字體體系(中文字體 + 英文字體)
  • 豐富的字號選擇(8px-64px)
  • 優化的 UI 設計,解決原生 Quill 樣式簡陋問題
  • 圖片 / 視頻上傳功能
  • Markdown 快捷操作支持
  • 響應式布局適配

為什么選擇 Quill?相比其他編輯器(如 TinyMCE、CKEditor),Quill 具有輕量、可擴展性強、API 友好等特點,非常適合需要自定義功能的場景。

二、環境準備與依賴安裝

2.1 基礎環境

  • Node.js (v14+)
  • Vue CLI (可選,用于快速創建項目)
  • Vue 2.x (當前 vue-quill-editor 對 Vue 3 支持有限)

2.2 依賴安裝

# 安裝核心編輯器
npm install vue-quill-editor --save# 安裝Quill本體
npm install quill --save# 安裝Markdown快捷鍵插件
npm install quill-markdown-shortcuts --save# 安裝圖片上傳擴展模塊
npm install quill-image-super-solution-module --save

三、組件封裝

<template><div class="quill-editor-container"><!-- 富文本編輯器主體 --><quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" class="editor"@input="handleContentChange"></quill-editor><!-- 視頻上傳隱藏輸入框 --><input type="file" id="video-upload-input" accept="video/*" style="display: none" @change="handleVideoUpload" /></div>
</template><script>
// 引入Quill編輯器樣式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'// 引入Vue-Quill編輯器組件和Quill核心庫
import { quillEditor, Quill } from 'vue-quill-editor'// 引入Markdown快捷操作插件
import MarkdownShortcuts from 'quill-markdown-shortcuts'// 引入圖片上傳擴展模塊
import { container, ImageExtend, QuillWatch } from "quill-image-super-solution-module"// 引入HTTP請求工具
import request from "@/utils/request"// 引入圖片處理混入
import imageMixin from "@/mixins/imageMixin"// 注冊Markdown快捷鍵模塊
Quill.register('modules/markdownShortcuts', MarkdownShortcuts)// 注冊圖片擴展模塊
Quill.register('modules/ImageExtend', ImageExtend)// 字體配置
const fonts = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong','YouYuan', 'LiSu', 'STSong', 'STZhongsong', 'STKaiti','STFangsong', 'Arial', 'Times-New-Roman', 'Courier-New', 'Verdana','Georgia', 'Impact', 'Comic-Sans-MS', 'sans-serif', 'serif', 'monospace'
]
const Font = Quill.import('formats/font')
Font.whitelist = fonts
Font.format = function (node, value) {if (value) {fonts.forEach(font => node.classList.remove(`ql-font-${font}`));node.classList.add(`ql-font-${value}`);} else {fonts.forEach(font => node.classList.remove(`ql-font-${font}`));}
};
Quill.register(Font, true)// 字號配置
const sizes = ['8px', '10px', '12px', '14px', '16px', '18px','20px', '22px', '24px', '26px', '28px','30px', '32px', '36px', '40px', '48px', '56px', '64px'
]
const Size = Quill.import('formats/size')
Size.whitelist = sizes
Quill.register(Size, true)// 自定義視頻Blot
const VideoBlot = Quill.import('formats/video')
const ATTRIBUTES = ['height', 'width', 'controls']if (!Quill.imports['formats/custom-video']) {class CustomVideoBlot extends VideoBlot {static formats(domNode) {return ATTRIBUTES.reduce((formats, attribute) => {if (domNode.hasAttribute(attribute)) {formats[attribute] = domNode.getAttribute(attribute)}return formats}, {})}format(name, value) {if (ATTRIBUTES.includes(name)) {if (value) {this.domNode.setAttribute(name, value)} else {this.domNode.removeAttribute(name)}} else {super.format(name, value)}}}CustomVideoBlot.blotName = 'custom-video'CustomVideoBlot.tagName = 'VIDEO'Quill.register(CustomVideoBlot)
}export default {name: 'RichTextEditor', // 組件名稱,用于注冊和引用mixins: [imageMixin],components: { quillEditor },props: {// 接收外部傳入的內容,實現雙向綁定value: {type: String,default: ''},// 編輯器高度height: {type: Number,default: 500},// 圖片上傳接口地址imageUploadUrl: {type: String,default: '/api/v1/cos/batch/upload/article'},// 視頻上傳接口地址videoUploadUrl: {type: String,default: '/cos/batch/upload/video'},// 最大圖片大小(MB)maxImageSize: {type: Number,default: 2},// 最大視頻大小(MB)maxVideoSize: {type: Number,default: 50}},data() {return {content: this.value, // 內部維護的內容狀態uploadedImages: [], // 已上傳圖片列表uploadedVideos: [], // 已上傳視頻列表editorOption: {theme: 'snow',modules: {markdownShortcuts: {},ImageExtend: {loading: true,name: 'files',size: this.maxImageSize,action: this.imageUploadUrl,accept: 'image/jpg, image/png, image/gif, image/jpeg, image/bmp, image/x-icon',response: (res) => {const imageUrl = res.data[0]this.uploadedImages.push(imageUrl)// 觸發圖片上傳成功事件this.$emit('image-uploaded', imageUrl)return this.getImageUrl(imageUrl)},headers: (xhr) => {const token = localStorage.getItem('token') || ''if (token) {xhr.setRequestHeader('Authorization', `Bearer ${token}`)}},sizeError: () => {this.$message.error(`圖片大小不能超過 ${this.maxImageSize}MB!`)},error: (err) => {this.$message.error('圖片上傳失敗,請重試')this.$emit('upload-error', { type: 'image', error: err })console.error('圖片上傳錯誤:', err)},change: (xhr, formData) => {formData.append('type', 'article')}},toolbar: {container: [[{ 'font': fonts }],[{ 'size': sizes }],['bold', 'italic', 'underline', 'strike'],[{ 'color': [] }, { 'background': [] }],[{ 'script': 'sub' }, { 'script': 'super' }],[{ 'header': 1 }, { 'header': 2 }],[{ 'list': 'ordered' }, { 'list': 'bullet' }],[{ 'indent': '-1' }, { 'indent': '+1' }],[{ 'align': [] }],['link', 'image', 'video'],['blockquote', 'code-block'],['clean']],handlers: {'image': function () {QuillWatch.emit(this.quill.id)},'video': function () {document.getElementById('video-upload-input').click()}}}}}}},watch: {// 監聽外部傳入的value變化,同步到組件內部value(newVal) {if (newVal !== this.content) {this.content = newVal}},// 監聽高度變化,更新編輯器樣式height(newVal) {this.$nextTick(() => {const editorEl = this.$el.querySelector('.editor')if (editorEl) {editorEl.style.minHeight = `${newVal}px`}})}},methods: {// 內容變化時觸發,向父組件傳遞最新內容handleContentChange() {this.$emit('input', this.content)this.$emit('change', this.content)},// 處理視頻上傳async handleVideoUpload(e) {const file = e.target.files[0]if (!file) return// 驗證視頻文件if (!this.validateVideoFile(file)) {e.target.value = ''return}// 顯示加載中const loading = this.$loading({lock: true,text: '視頻上傳中,請稍候...',spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'})try {const formData = new FormData()formData.append('files', file)// 上傳視頻const res = await request({url: this.videoUploadUrl,method: 'post',data: formData,headers: { 'Content-Type': 'multipart/form-data' }})if (!res || !res.data || res.data.length === 0) {throw new Error('視頻上傳失敗,返回格式不正確')}// 處理上傳結果const videoUrl = res.data[0]this.uploadedVideos.push(videoUrl)this.$emit('video-uploaded', videoUrl)// 將視頻插入編輯器const quill = this.$refs.myQuillEditor.quillconst range = quill.getSelection()const insertIndex = range ? range.index : quill.getLength() - 1quill.insertEmbed(insertIndex, 'custom-video', this.getImageUrl(videoUrl))// 設置視頻屬性this.$nextTick(() => {const lastIndex = quill.getLength() - 1const [videoBlot] = quill.getLine(lastIndex)if (videoBlot && videoBlot.statics.blotName === 'custom-video') {videoBlot.format('controls', 'controls')videoBlot.format('width', '100%')videoBlot.format('height', 'auto')}quill.setSelection(lastIndex + 1)})this.$message.success('視頻上傳成功')} catch (error) {console.error('視頻上傳錯誤詳情:', error)this.$message.error(`視頻上傳失敗: ${error.message || '未知錯誤'}`)this.$emit('upload-error', { type: 'video', error: error })} finally {loading.close()e.target.value = '' // 重置輸入框,允許重復上傳同一文件}},// 驗證視頻文件格式和大小validateVideoFile(file) {const videoTypes = ['video/mp4', 'video/ogg', 'video/webm', 'video/avi', 'video/mov']if (!videoTypes.includes(file.type)) {this.$message.error('請上傳支持的視頻格式(MP4、OGG、WEBM、AVI、MOV)')return false}const maxSizeBytes = this.maxVideoSize * 1024 * 1024if (file.size > maxSizeBytes) {this.$message.error(`視頻大小不能超過 ${this.maxVideoSize}MB`)return false}return true},// 獲取編輯器實例getEditorInstance() {return this.$refs.myQuillEditor.quill},// 清空編輯器內容clearContent() {this.content = ''this.$emit('input', '')},// 獲取已上傳的媒體文件列表getUploadedFiles() {return {images: [...this.uploadedImages],videos: [...this.uploadedVideos]}}}
}
</script><style scoped>
.quill-editor-container {width: 100%;box-sizing: border-box;
}.editor {min-height: 500px;
}::v-deep .ql-container {min-height: 400px !important;border: 1px solid #e5e7eb !important;border-radius: 0 0 6px 6px;
}::v-deep .ql-toolbar {border: 1px solid #e5e7eb !important;border-bottom: none !important;border-radius: 6px 6px 0 0;background-color: #f9fafb;
}::v-deep .ql-editor img,
::v-deep .ql-editor video {max-width: 100%;height: auto;margin: 10px 0;
}::v-deep .ql-editor video {min-height: 300px;border: 1px solid #eee;
}
</style><style>
.ql-snow .ql-picker.ql-font {width: 140px;margin-right: 8px;height: 30px;display: flex;align-items: center;
}/* 字號選擇器樣式優化 */
.ql-snow .ql-picker.ql-size {width: 80px;margin-right: 8px;height: 30px;display: flex;align-items: center;
}/* 下拉菜單容器優化 - 解決選項過多問題 */
.ql-snow .ql-picker.ql-font .ql-picker-options {max-height: 280px;overflow-y: auto;border-radius: 6px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);border: 1px solid #e2e8f0;padding: 4px 0;width: 140px;
}.ql-snow .ql-picker.ql-size .ql-picker-options {max-height: 280px;overflow-y: auto;border-radius: 6px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);border: 1px solid #e2e8f0;padding: 4px 0;width: 80px;
}/* 滾動條美化 */
.ql-snow .ql-picker-options::-webkit-scrollbar {width: 6px;
}.ql-snow .ql-picker-options::-webkit-scrollbar-track {background: #f1f5f9;border-radius: 3px;
}.ql-snow .ql-picker-options::-webkit-scrollbar-thumb {background: #cbd5e1;border-radius: 3px;
}.ql-snow .ql-picker-options::-webkit-scrollbar-thumb:hover {background: #94a3b8;
}/* 下拉菜單項樣式優化 */
.ql-snow .ql-picker-item {height: 30px;line-height: 30px;padding: 0 12px;transition: all 0.2s ease;white-space: nowrap;
}.ql-snow .ql-picker-item:hover {background-color: #f1f5f9;padding-left: 14px;
}.ql-snow .ql-picker-item.ql-selected {background-color: #e0f2fe;color: #0284c7;font-weight: 500;
}/* 選擇器按鈕樣式 */
.ql-snow .ql-picker-label {height: 32px;line-height: 32px;padding: 0 8px;border-radius: 4px;transition: background-color 0.2s;
}.ql-snow .ql-picker-label:hover {background-color: #f8fafc;
}/* 字體樣式定義 - 確保生效 */
.ql-editor {font-size: 16px;line-height: 1.6;
}/* 中文字體樣式 */
.ql-editor .ql-font-SimSun {font-family: "SimSun", "宋體", serif !important;
}.ql-editor .ql-font-SimHei {font-family: "SimHei", "黑體", sans-serif !important;
}.ql-editor .ql-font-Microsoft-YaHei {font-family: "Microsoft YaHei", "微軟雅黑", sans-serif !important;
}.ql-editor .ql-font-KaiTi {font-family: "KaiTi", "楷體", serif !important;
}.ql-editor .ql-font-FangSong {font-family: "FangSong", "仿宋", serif !important;
}.ql-editor .ql-font-YouYuan {font-family: "YouYuan", "幼圓", sans-serif !important;
}.ql-editor .ql-font-LiSu {font-family: "LiSu", "隸書", serif !important;
}.ql-editor .ql-font-STSong {font-family: "STSong", "宋體-繁", serif !important;
}.ql-editor .ql-font-STZhongsong {font-family: "STZhongsong", "中宋-繁", serif !important;
}.ql-editor .ql-font-STKaiti {font-family: "STKaiti", "楷體-繁", serif !important;
}.ql-editor .ql-font-STFangsong {font-family: "STFangsong", "仿宋-繁", serif !important;
}/* 英文字體樣式 */
.ql-editor .ql-font-Arial {font-family: "Arial", sans-serif !important;
}.ql-editor .ql-font-Times-New-Roman {font-family: "Times New Roman", serif !important;
}.ql-editor .ql-font-Courier-New {font-family: "Courier New", monospace !important;
}.ql-editor .ql-font-Verdana {font-family: "Verdana", sans-serif !important;
}.ql-editor .ql-font-Georgia {font-family: "Georgia", serif !important;
}.ql-editor .ql-font-Impact {font-family: "Impact", sans-serif !important;
}.ql-editor .ql-font-Comic-Sans-MS {font-family: "Comic Sans MS", cursive !important;
}.ql-editor .ql-font-sans-serif {font-family: "sans-serif" !important;
}.ql-editor .ql-font-serif {font-family: "serif" !important;
}.ql-editor .ql-font-monospace {font-family: "monospace" !important;
}/* 下拉菜單字體顯示 */
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {content: '默認';
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimSun"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimSun"]::before {content: '宋體';font-family: "SimSun", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimHei"]::before {content: '黑體';font-family: "SimHei", sans-serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Microsoft-YaHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Microsoft-YaHei"]::before {content: '微軟雅黑';font-family: "Microsoft YaHei", sans-serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="KaiTi"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="KaiTi"]::before {content: '楷體';font-family: "KaiTi", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="FangSong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="FangSong"]::before {content: '仿宋';font-family: "FangSong", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="YouYuan"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="YouYuan"]::before {content: '幼圓';font-family: "YouYuan", sans-serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="LiSu"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="LiSu"]::before {content: '隸書';font-family: "LiSu", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="STSong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="STSong"]::before {content: '宋體-繁';font-family: "STSong", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="STZhongsong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="STZhongsong"]::before {content: '中宋-繁';font-family: "STZhongsong", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="STKaiti"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="STKaiti"]::before {content: '楷體-繁';font-family: "STKaiti", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="STFangsong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="STFangsong"]::before {content: '仿宋-繁';font-family: "STFangsong", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {content: 'Arial';font-family: "Arial", sans-serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Times-New-Roman"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Times-New-Roman"]::before {content: 'Times New Roman';font-family: "Times New Roman", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Courier-New"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Courier-New"]::before {content: 'Courier New';font-family: "Courier New", monospace;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Verdana"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Verdana"]::before {content: 'Verdana';font-family: "Verdana", sans-serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Georgia"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Georgia"]::before {content: 'Georgia';font-family: "Georgia", serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Impact"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Impact"]::before {content: 'Impact';font-family: "Impact", sans-serif;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Comic-Sans-MS"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Comic-Sans-MS"]::before {content: 'Comic Sans';font-family: "Comic Sans MS", cursive;
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="sans-serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="sans-serif"]::before {content: '無襯線';font-family: "sans-serif";
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {content: '襯線';font-family: "serif";
}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {content: '等寬';font-family: "monospace";
}/* 字號樣式 */
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {content: '16px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="8px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="8px"]::before {content: '8px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="10px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="10px"]::before {content: '10px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {content: '12px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {content: '14px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {content: '16px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {content: '18px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {content: '20px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {content: '22px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {content: '24px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {content: '26px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before {content: '28px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="30px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="30px"]::before {content: '30px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {content: '32px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="36px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="36px"]::before {content: '36px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="40px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="40px"]::before {content: '40px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="48px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="48px"]::before {content: '48px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="56px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="56px"]::before {content: '56px';
}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="64px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="64px"]::before {content: '64px';
}/* 編輯器內容字號樣式 */
.ql-editor .ql-size-8px {font-size: 8px !important;
}.ql-editor .ql-size-10px {font-size: 10px !important;
}.ql-editor .ql-size-12px {font-size: 12px !important;
}.ql-editor .ql-size-14px {font-size: 14px !important;
}.ql-editor .ql-size-16px {font-size: 16px !important;
}.ql-editor .ql-size-18px {font-size: 18px !important;
}.ql-editor .ql-size-20px {font-size: 20px !important;
}.ql-editor .ql-size-22px {font-size: 22px !important;
}.ql-editor .ql-size-24px {font-size: 24px !important;
}.ql-editor .ql-size-26px {font-size: 26px !important;
}.ql-editor .ql-size-28px {font-size: 28px !important;
}.ql-editor .ql-size-30px {font-size: 30px !important;
}.ql-editor .ql-size-32px {font-size: 32px !important;
}.ql-editor .ql-size-36px {font-size: 36px !important;
}.ql-editor .ql-size-40px {font-size: 40px !important;
}.ql-editor .ql-size-48px {font-size: 48px !important;
}.ql-editor .ql-size-56px {font-size: 56px !important;
}.ql-editor .ql-size-64px {font-size: 64px !important;
}
</style>

四、使用

// 使用
<quill-markdown v-model="articleForm.content" :height="600" :max-image-size="5":max-video-size="100" @image-uploaded="handleImageUploaded"@video-uploaded="handleVideoUploaded"></quill-markdown>// 引入
import quillMarkdown from '../../components/quill-Markdown.vue'
// 注冊components: {quillMarkdown},

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918908.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918908.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918908.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#內嵌字符串格式化輸出

內嵌字符串格式輸出 double speedOfLight 299792.458;System.Globalization.CultureInfo.CurrentCulture System.Globalization.CultureInfo.GetCultureInfo("nl-NL"); string messageInCurrentCulture $"The speed of light is {speedOfLight:N3} km/s.&quo…

ThreeJS程序化生成城市大場景底座(性能測試)

一、簡介基于矢量geojson數據構建建筑、植被、道路等&#xff0c;實現城市場景底座。涉及渲染的性能優化無非就是眾所周知的那些事兒。視錐剔除、mesh合并、減少draw call、四叉樹、八叉樹、數據壓縮、WebWorker、著色器優化等。下面是對東莞市數十萬建筑以及海量3D樹的渲染測試…

?電風扇離線語音芯片方案設計與應用場景:基于 8 腳 MCU 與 WTK6900P 的創新融合

?電風扇離線語音芯片方案設計與應用場景&#xff1a;基于 8 腳 MCU 與 WTK6900P 的創新融合一、引言在智能家居領域蓬勃發展的當下&#xff0c;用戶對于家電產品的智能化和便捷性需求日益增長。傳統的電風扇控制方式&#xff0c;如按鍵操作或遙控器控制&#xff0c;在某些場景…

(第四篇)spring cloud之Consul注冊中心

目錄 一、介紹 二、安裝 三、整合代碼使用 1、創建服務提供者8006 2、創建服務消費者80 3、Eureka、zookeeper和consul的異同點 一、介紹 Consul 是一套開源的分布式服務發現和配置管理系統&#xff0c;由 HashiCorp 公司用 Go 語言開發。它提供了微服務系統中的服務治理…

NAT 和 PNAT

核心概念與背景 IPv4 地址枯竭&#xff1a; IPv4 地址空間有限&#xff08;約 42.9 億個&#xff09;&#xff0c;早已分配殆盡。NAT/PNAT 是緩解此問題的最重要、最廣泛部署的技術。私有 IP 地址空間&#xff1a; IANA 保留了三個 IPv4 地址段專供私有網絡內部使用&#xff08…

windows系統創建FTP服務

一丶開啟FTP功能 控制面板->程序與功能->啟用或關閉windows功能->Internet Information Services->勾選FTP服務器二丶創建FTP服務 1丶控制面板->windows工具->Internet Information Services (IIS) 管理器2丶網站->添加FTP站點->輸入對應內容3丶點擊新…

DeepSeek補全IBM MQ 9.4 REST API 執行命令的PPT

DeepSeek補全了我在網上找到的PPT的一頁內容&#xff0c;幫了大忙了。人機協同&#xff0c;人工智能可以協助人更好的做事。下面的內容是講解IBM MQ REST API 執行IBM MQ命令的PPT: MQSC for REST Tailored RESTful support for individual MQ objects and actions are in the …

【swift】SwiftUI動畫卡頓全解:GeometryReader濫用檢測與Canvas繪制替代方案

SwiftUI動畫卡頓全解&#xff1a;GeometryReader濫用檢測與Canvas繪制替代方案一、GeometryReader的性能陷阱深度解析1. 布局計算機制2. 動畫中的災難性表現二、GeometryReader濫用檢測系統1. 靜態代碼分析器2. 運行時性能監控三、Canvas繪制優化方案1. 基礎Canvas實現2. 性能優…

悄悄話、合唱層次感:聲網空間音頻解鎖語聊新玩法

作為語聊房主播&#xff0c;我曾覺得線上相聚差點意思。多人開麥時聲音混雜&#xff0c;互動缺真實感&#xff0c;觀眾留不住&#xff0c;自己播著也沒勁。直到平臺接入聲網空間音頻&#xff0c;一切改觀&#xff0c;觀眾說像在真實房間聊天&#xff0c;留存率漲 35%&#xff0…

【工具】多圖裁剪批量處理工具

文章目錄工具核心功能亮點1. 批量上傳與智能管理2. 精準直觀的裁剪控制3. 一鍵應用與批量處理為什么這個工具能提升你的工作效率&#xff1f;統一性與一致性保證節省90%以上的時間專業級功能&#xff0c;零學習成本實際應用場景電子商務攝影工作內容創作教育領域技術優勢完全在…

如何提升需求分析能力

要系統性地提升需求分析能力&#xff0c;核心在于實現從一個被動的“需求記錄員”&#xff0c;向一個主動的、價值驅動的“業務問題解決者”的深刻轉型。要完成這一蛻變&#xff0c;必須在五個關鍵領域進行系統性的修煉與實踐&#xff1a;培養“穿透表象”的系統思維能力、掌握…

另類的pdb恢復方式

cdb中有pdb1,pdb2 需求&#xff1a;希望將在線熱備份pdb1的備份集a&#xff0c;恢復成pdb3&#xff0c;使得cdb中有pdb1,2,3 參考到的&#xff1a;RMAN備份恢復典型案例——跨平臺遷移pdb - 墨天輪 ORA-65122: Pluggable Database GUID Conflicts With The GUID Of An Existi…

HarmonyOS 實戰:用 @Observed + @ObjectLink 玩轉多組件實時數據更新

摘要 在鴻蒙&#xff08;HarmonyOS&#xff09;應用開發中&#xff0c;實時數據更新是一個繞不開的話題&#xff0c;尤其是在你封裝了很多自定義組件、需要多個組件之間共享和同步數據的場景里。過去我們可能會依賴父子組件直接傳參或全局狀態管理&#xff0c;但這樣寫會讓代碼…

云原生俱樂部-雜談2

說實話&#xff0c;雜談系列可能會比較少&#xff0c;因為畢竟大部分時間都是上的線上&#xff0c;迄今為止也是&#xff0c;和雷老師與WH的交流不是很多。這個系列僅僅是我在做其他筆記部分無聊的時候來寫的&#xff0c;內容也沒有規劃過&#xff0c;隨想隨寫。倒不是時間太多…

波浪模型SWAN學習(1)——模型編譯與波浪折射模擬(Test of the refraction formulation)

SWAN模型編譯與波浪折射模擬&#xff08;Test of the refraction formulation&#xff09;編譯過程算例簡介參數文件文件頭&#xff08;HEADING&#xff09;計算區域和網格地形數據邊界條件物理模塊設置輸出設置執行參數模擬結果由于工作原因&#xff0c;最近開始接觸波浪模型&…

更換cmd背景圖片

打開cmd 右擊頂部&#xff0c;選擇設置選擇命令提示符&#xff0c;外觀選擇背景圖像路徑更改成自己的圖片&#xff0c;然后右下角保存 設置成功

基于RobustVideoMatting(RVM)進行視頻人像分割(torch、onnx版本)

發表時間&#xff1a;2021年8月25日 項目地址&#xff1a;https://peterl1n.github.io/RobustVideoMatting/ 論文閱讀&#xff1a;https://hpg123.blog.csdn.net/article/details/134409222 RVM是字節團隊開源的一個實時人像分割模型&#xff0c;基于LSTMConv實現&#xff0c;…

強制從不抱怨環境。

警世俗語&#xff1a;強者逆襲心法&#xff08;句句穿心&#xff09;環境是泥潭&#xff1f;那就讓它開出金蓮&#xff01; —— 抱怨是弱者的裹腳布&#xff0c;行動是強者的登天梯。爛泥里也能種出搖錢樹&#xff0c;關鍵看你敢不敢下手挖&#xff01;老天爺發牌爛&#xff1…

MC0439符號統計

碼蹄集OJ-符號統計 MC0439?符號統計 難度&#xff1a;黃金 時間限制&#xff1a;1 秒 占用內存&#xff1a;256 M 收藏 報錯 在華容道放曹的緊張時刻&#xff0c;小碼哥接到了一個看似微不足道卻至關重要的任務&#xff1a;解讀一條僅由小寫英文字母組成的神秘字符串 s&#…

Android Jetpack 系列(五)Room 本地數據庫實戰詳解

1. 簡介 在需要輕量級本地持久化的場景中&#xff0c;DataStore 是一個理想的選擇&#xff08;詳見《Android Jetpack 系列&#xff08;四&#xff09;DataStore 全面解析與實踐》&#xff09;。但當你面臨如下需求時&#xff0c;本地數據庫便顯得尤為重要&#xff1a; 復雜的…