vue專案裡修改Quill內建的video blot,用video標籤替換iframe
阿新 • • 發佈:2019-01-11
vue專案裡修改Quill內建的video blot,用video標籤替換iframe
既然搜到這了,quill的基本安裝使用就不多說了,quill內建的video模組是使用iframe標籤,用視訊網站上視訊分享連線沒問題的,因為專案上用伺服器本地的MP4視訊,本來iframe的src直接指.mp4檔案也是可以的,其他瀏覽器都可以,但是還有個感人的IE,iframe裡直接指向.mp4時IE會變成下載,只好把iframe改成H5原生的video標籤
參考了quill的原始碼,直接拷貝video.js模組後修改,在vue工程目錄下建立quill資料夾及檔案:src\quill\video.js
import { Quill } from 'vue-quill-editor'
// 原始碼中是import直接倒入,這裡要用Quill.import引入
const BlockEmbed = Quill.import('blots/block/embed')
const Link = Quill.import('formats/link')
const ATTRIBUTES = ['height', 'width']
class Video extends BlockEmbed {
static create (value) {
const node = super.create (value)
// 新增video標籤所需的屬性
node.setAttribute('controls', 'controls')
node.setAttribute('type', 'video/mp4')
node.setAttribute('src', this.sanitize(value))
return node
}
static formats (domNode) {
return ATTRIBUTES.reduce((formats, attribute) => {
if (domNode.hasAttribute (attribute)) {
formats[attribute] = domNode.getAttribute(attribute)
}
return formats
}, {})
}
static sanitize (url) {
return Link.sanitize(url) // eslint-disable-line import/no-named-as-default-member
}
static value (domNode) {
return domNode.getAttribute('src')
}
format (name, value) {
if (ATTRIBUTES.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value)
} else {
this.domNode.removeAttribute(name)
}
} else {
super.format(name, value)
}
}
html () {
const { video } = this.value()
return `<a href="${video}">${video}</a>`
}
}
Video.blotName = 'video' // 這裡不用改,樓主不用iframe,直接替換掉原來,如果需要也可以保留原來的,這裡用個新的blot
Video.className = 'ql-video'
Video.tagName = 'video' // 用video標籤替換iframe
export default Video
vue元件中引入quill
<template>
<div class="post-editor">
<media-card :fiche="post" @editCover="editCover" editable />
<quill-editor
v-model="post.content"
:options="editorOption"
style="min-height: 200px; margin-bottom: 54px"
ref="newEditor"
@change="onEditorChange($event)">
</quill-editor>
<div class="button-box row justify-end">
<q-btn icon="save" label="儲存" color="tpNav" :disable="notValid" @click="savePost" style="padding: 0 2rem;" />
</div>
<vue-transmit
tag="div"
v-bind="uploadoptions"
@success="filehandle"
@error="errhandle"
@upload-progress="upgress"
ref="uploader" />
</div>
</template>
<script>
import { mapState } from 'vuex'
import * as Quill from 'quill'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import {quillEditor} from 'vue-quill-editor'
import mediaCard from '../../components/mediacard'
// quill編輯器的字型
var fonts = ['Microsoft-YaHei', 'SimSun', 'SimHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif']
var Font = Quill.import('formats/font')
Font.whitelist = fonts
Quill.register(Font, true)
// 這裡引入修改過的video模組並註冊
import Video from '../../quill/video'
Quill.register(Video, true)
export default {
name: 'cmseditor',
components: {
quillEditor,
mediaCard
},
props: {
reportId: {
type: String,
default: ''
}
},
data () {
return {
saving: false,
changeCover: false,
changeDelay: 300,
delayFlag: true,
pictures: [],
uplaodBase: '/api/storage/upload/',
uploadoptions: {
acceptedFileTypes: ['image/*'],
url: '',
clickable: false,
headers: {
Authorization: `Bearer ${this.$store.state.auth.token}`
}
},
progress: 0,
post: {
'_id': '',
title: '',
date: '',
cover: '',
abstract: '',
attachments: [],
content: ''
},
editorOption: {
modules: {
toolbar: [
['bold', 'italic', 'underline'],
['blockquote'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': fonts }],
[{ 'align': [] }],
['clean'],
['image', 'video']
],
history: {
delay: 1000,
maxStack: 50,
userOnly: false
}
},
placeholder: '輸入內容'
},
addImgRange: ''
}
},
computed: {
...mapState('layout', ['isMobile', 'winWidth']),
notValid () {
const { content, title, date } = this.post
return this.saving || !content || !title || !date
},
newReport: () => this.reportId.length === 0
},
mounted () {
// 定義圖片按鈕的功能,使用上傳伺服器後返回的連結替換掉quill內建base64編碼方式
let imgHandler = async (image) => {
this.addImgRange = this.$refs.newEditor.quill.getSelection()
if (image) {
this.$refs.uploader.triggerBrowseFiles()
}
}
this.$refs.newEditor.quill.getModule('toolbar').addHandler('image', imgHandler)
if (this.reportId === 'new') {
this.newPost()
} else {
this.getPost(this.reportId)
}
},
methods: {
editCover (id) {
if (!id) return
this.changeCover = true
this.$refs.uploader.triggerBrowseFiles()
},
savePost () {
this.saving = true
if (this.reportId === 'new') {
this.$axios.post('/post/new', this.post).then(res => {
this.saving = false
this.$q.notify({
type: 'positive',
message: '儲存成功'
})
this.$router.replace({name: 'cmsreports'})
}).catch(err => {
this.saving = false
console.log(err)
this.$q.notify('儲存失敗')
})
} else {
this.$axios.put('/post/' + this.post._id, this.post).then(res => {
this.$q.notify({
type: 'positive',
message: '儲存成功'
})
this.save = false
this.$router.replace({name: 'cmsreports'})
}).catch(err => {
this.save = false
console.log(err)
this.$q.notify('儲存失敗')
})
}
},
onEditorChange ({ quill, html, text }) {
if (this.delayFlag) {
this.delayFlag = false
this.post.abstract = text.length > 70 ? text.substr(0, 70) : text
setTimeout(() => {
this.delayFlag = true
}, this.changeDelay)
}
},
filehandle (file, res, prog) {
var value = res.src
if (this.changeCover) {
this.post.cover = value
this.changeCover = false
} else {
let index = this.addImgRange != null ? this.addImgRange.index : 0 // 獲取插入時的位置索引,如果獲取失敗,則插入到最前面
this.$refs.newEditor.quill.insertEmbed(index, 'image', value, Quill.sources.USER)
if (!this.post.cover) this.post.cover = value
this.pictures.push(value)
}
},
errhandle (file, res, prog) {
this.changeCover = false
this.$q.notify({
type: 'warning',
message: '上傳失敗'
})
},
upgress (file, progress, sent) {
this.progress = progress
},
getPost (id) {
this.$axios.get('/post/' + id).then(res => {
this.post = res.data
this.uploadoptions.url = this.uplaodBase + this.post._id
}).catch(err => {
console.log(err)
})
},
newPost () {
this.$axios.get('/post/new').then(res => {
this.post._id = res.data.id
this.uploadoptions.url = this.uplaodBase + this.post._id
}).catch(err => {
console.log(err)
})
}
}
}
</script>
.ql-editor .ql-video {
width: 640px;
height: 480px;
}
.ql-size-small {
font-size: 0.8rem;
}
.ql-size-normal {
font-size: 1rem;
}
.ql-size-large {
font-size: 1.2rem;
}
.ql-size-huge {
font-size: 1.5rem;
font-weight: bold;
}
這樣就ok了,簡單的說就是分三步
1、修改video.js
2、vue中引入video.js
3、quill註冊引入的video模組
使用和原來的一樣,彈出url輸入框時輸入MP4檔案的url地址就可以了