element ui富文本編輯器的使用(quill-editor)
效果展示:(可以上傳圖片及其視頻)
可以拖拽圖片大小及其位置
第一步、首先安裝富文本編輯器插件
cnpm install vue-quill-editor --save
cnpm install quill-image-drop-module --save
cnpm install quill-image-resize-module --save
第二步、然后在main.js文件中,全局注冊
//引入quill-editor編輯器
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor)
//實現(xiàn)quill-editor編輯器拖拽上傳圖片
import * as Quill from 'quill'
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/imageDrop', ImageDrop)
//實現(xiàn)quill-editor編輯器調(diào)整圖片尺寸
import ImageResize from 'quill-image-resize-module'
Quill.register('modules/imageResize', ImageResize)
第三步、在vue界面中使用quill-editor
為了便于大家直接使用,直接把script以及css放在一個頁面里,之際copy就可以使用
<template>
<div>
<div>
<el-button @click="openContent" type="primary">查看元素</el-button>
</div>
<div id='quillEditorQiniu'>
<!-- 基于elementUi的上傳組件 el-upload begin-->
<el-upload
class="avatar-uploader"
:action="uploadImgUrl"
:accept="'image/*,video/*'"
:show-file-list="false"
:on-success="uploadEditorSuccess"
:on-error="uploadEditorError"
:before-upload="beforeEditorUpload"
:headers="headers">
</el-upload>
<!-- 基于elementUi的上傳組件 el-upload end-->
<quill-editor class="editor" v-model="content" ref="customQuillEditor" :options="editorOption" >
</quill-editor>
</div>
</div>
</template>
<script>
import * as Quill from 'quill'
// 這里引入修改過的video模塊并注冊
import Video from './video'
Quill.register(Video, true)
//獲取登錄token,引入文件,如果只是簡單測試,沒有上傳文件是否登錄的限制的話,
//這個token可以不用獲取,文件可以不引入,把上面對應的上傳文件攜帶請求頭 :headers="headers" 這個代碼刪掉即可
import {getToken} from "@/utils/auth";
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
['link', 'image', 'video'],
['clean'] // remove formatting button
];
export default {
data(){
return {
headers: {
Authorization: "Bearer " + getToken(),
},
uploadImgUrl:"/v1/admin/common/upload",
uploadUrlPath:"沒有文件上傳",
quillUpdateImg:false,
content:'', //最終保存的內(nèi)容
editorOption:{
placeholder:'你想說什么?',
modules: {
imageResize: {
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white'
},
modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]
},
toolbar: {
container: toolbarOptions, // 工具欄
handlers: {
'image': function (value) {
if (value) {
document.querySelector('#quillEditorQiniu .avatar-uploader input').click()
} else {
this.quill.format('image', false);
}
},
'video': function (value) {
if (value) {
document.querySelector('#quillEditorQiniu .avatar-uploader input').click()
} else {
this.quill.format('video', false);
}
},
}
}
}
},
}
},
methods:{
//上傳圖片之前async
beforeEditorUpload(res, file){
//顯示上傳動畫
this.quillUpdateImg = true;
// const res1 = await uploadImage()
// console.log(res1,'=====');
// this.$emit('before',res, file)
console.log(res);
console.log(file);
},
// 上傳圖片成功
uploadEditorSuccess(res, file) {
console.log("上傳成功")
// this.$emit('upload',res, file)
console.log(res, file);
//拼接出上傳的圖片在服務器的完整地址
let imgUrl=res.data.url;
let type=imgUrl.substring(imgUrl.lastIndexOf(".")+1);
console.log(type);
// 獲取富文本組件實例
let quill = this.$refs.customQuillEditor.quill;
// 獲取光標所在位置
let length = quill.getSelection().index;
// 插入圖片||視頻 res.info為服務器返回的圖片地址
if(type=='mp4' || type=='MP4'){
quill.insertEmbed(length, 'video', imgUrl)
}else{
quill.insertEmbed(length, 'image', imgUrl)
}
// 調(diào)整光標到最后
quill.setSelection(length + 1)
//取消上傳動畫
this.quillUpdateImg = false;
},
// 上傳(文件)圖片失敗
uploadEditorError(res, file) {
console.log(res);
console.log(file);
//頁面提示
this.$message.error('上傳圖片失敗')
//取消上傳動畫
this.quillUpdateImg = false;
},
//上傳組件返回的結(jié)果
uploadResult:function (res){
this.uploadUrlPath=res;
},
openContent:function (){
console.log(this.content)
},
},
created () {
},
//只執(zhí)行一次,加載執(zhí)行
mounted () {
console.log("開始加載")
// 初始給編輯器設置title
},
watch:{
content(newVal, oldVal) {
//this.$emit('input', newVal);
console.log(newVal)
console.log(oldVal)
}
},
}
</script>
<style>
.editor {
line-height: normal !important;
height: 400px;
margin-bottom: 50px;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "請輸入鏈接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "請輸入視頻地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "標題1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "標題2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "標題3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "標題4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "標題5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "標題6";
}
.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="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "襯線字體";
}
.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: "等寬字體";
}
</style>
注意:
1、我是在elementUi使用的,上傳圖片以及頁面的訪問需要有登錄權(quán)限,所以我的上傳圖片視頻的組件里有:headers=“headers”,攜帶登錄權(quán)限
2、需要更改自己的上傳文件的路徑(改成自己的)
3、import {getToken} from “@/utils/auth”;
獲取登錄token,引入文件,如果只是簡單測試,沒有上傳文件是否登錄的限制的話,這個token可以不用獲取,文件可以不引入,把上面對應的上傳文件攜帶請求頭 :headers=“headers” 這個代碼刪掉即可。根據(jù)自己的情況來就行。
所引入的文件:(獲取登錄token)
如果上傳文件有登錄全選驗證,可以按照自己框架的token來寫,如果沒有則刪掉即可。
展示:
此時就quill-editor富文本編輯器就能使用了,除了基本功能之外也能夠上傳圖片
第四步:配置video.js(要有上傳視頻且回顯的功能需要配置)
因為quill-editor富文本編輯器當我們上傳mp4等視頻類型的文件時,quill-editor會自動的用iframe標簽來創(chuàng)建,此時視頻文件將不能顯示出來,我們需要改寫quill-editor提供能video.js文件,更改為video的標簽來展示視頻
------>此時視頻鏈接已經(jīng)生成,但是因為iframe標簽將不能展示
當我們手動的把頁面iframe標簽改為video標簽時視頻就顯示出來了,找到問題,開搞
1、創(chuàng)建video.js的空文件
為了方便講解,我這里放在了頁面同一目錄下
video.js內(nèi)容
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)
// console.log("js文件"+ window.jsValue)
// 添加video標簽所需的屬性
node.setAttribute('controls', 'controls') // 控制播放器
//刪除原生video的控制條的下載或者全屏按鈕的方法
//<video controls controlsList='nofullscreen nodownload noremote footbar' ></video>
//不用哪個在下面加上哪個
node.setAttribute('controlsList', 'nofullscreen') // 控制刪除
node.setAttribute('type', 'video/mp4')
node.setAttribute('style', 'object-fit:fill;width: 100%;')
node.setAttribute('preload', 'auto') // auto - 當頁面加載后載入整個視頻 meta - 當頁面加載后只載入元數(shù)據(jù) none - 當頁面加載后不載入視頻
node.setAttribute('playsinline', 'true')
node.setAttribute('x-webkit-airplay', 'allow')
// node.setAttribute('x5-video-player-type', 'h5') // 啟用H5播放器,是wechat安卓版特性
node.setAttribute('x5-video-orientation', 'portraint') // 豎屏播放 聲明了h5才能使用 播放器支付的方向,landscape橫屏,portraint豎屏,默認值為豎屏
node.setAttribute('x5-playsinline', 'true') // 兼容安卓 不全屏播放
node.setAttribute('x5-video-player-fullscreen', 'true') // 全屏設置,設置為 true 是防止橫屏
node.setAttribute('src', window.jsValue)
return node
}
static formats (domNode) {
return ATTRIBUTES.reduce((formats, attribute) => {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute)
}
return formats
}, {})
}
// static 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
2、更改vue界面(引入video.js文件)
(1) 引入video.js
import * as Quill from 'quill'
// 這里引入修改過的video模塊并注冊
import Video from './video'
Quill.register(Video, true)
(2) 引入全局變量(供video.js調(diào)用)
window.jsValue=imgUrl;
更好好后的vue文件:文章來源:http://www.zghlxwxcb.cn/news/detail-778786.html
<template>
<div>
<div>
<el-button @click="openContent" type="primary">查看元素</el-button>
</div>
<div id='quillEditorQiniu'>
<!-- 基于elementUi的上傳組件 el-upload begin-->
<el-upload
class="avatar-uploader"
:action="uploadImgUrl"
:accept="'image/*,video/*'"
:show-file-list="false"
:on-success="uploadEditorSuccess"
:on-error="uploadEditorError"
:before-upload="beforeEditorUpload"
:headers="headers">
</el-upload>
<!-- 基于elementUi的上傳組件 el-upload end-->
<quill-editor class="editor" v-model="content" ref="customQuillEditor" :options="editorOption" >
</quill-editor>
</div>
</div>
</template>
<script>
import * as Quill from 'quill'
// 這里引入修改過的video模塊并注冊
import Video from './video'
Quill.register(Video, true)
//自定義編輯器的工作條
import {getToken} from "@/utils/auth";
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
['link', 'image', 'video'],
['clean'] // remove formatting button
];
export default {
data(){
return {
headers: {
Authorization: "Bearer " + getToken(),
},
uploadImgUrl:"/v1/admin/common/upload",
uploadUrlPath:"沒有文件上傳",
quillUpdateImg:false,
content:'', //最終保存的內(nèi)容
editorOption:{
placeholder:'你想說什么?',
modules: {
imageResize: {
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white'
},
modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]
},
toolbar: {
container: toolbarOptions, // 工具欄
handlers: {
'image': function (value) {
if (value) {
document.querySelector('#quillEditorQiniu .avatar-uploader input').click()
} else {
this.quill.format('image', false);
}
},
'video': function (value) {
if (value) {
document.querySelector('#quillEditorQiniu .avatar-uploader input').click()
} else {
this.quill.format('video', false);
}
},
}
}
}
},
}
},
methods:{
//上傳圖片之前async
beforeEditorUpload(res, file){
//顯示上傳動畫
this.quillUpdateImg = true;
// const res1 = await uploadImage()
// console.log(res1,'=====');
// this.$emit('before',res, file)
console.log(res);
console.log(file);
},
// 上傳圖片成功
uploadEditorSuccess(res, file) {
console.log("上傳成功")
// this.$emit('upload',res, file)
console.log(res, file);
//拼接出上傳的圖片在服務器的完整地址
let imgUrl=res.data.url;
let type=imgUrl.substring(imgUrl.lastIndexOf(".")+1);
console.log(type);
// 獲取富文本組件實例
let quill = this.$refs.customQuillEditor.quill;
// 獲取光標所在位置
let length = quill.getSelection().index;
// 插入圖片||視頻 res.info為服務器返回的圖片地址
if(type=='mp4' || type=='MP4'){
window.jsValue=imgUrl;
quill.insertEmbed(length, 'video', imgUrl)
}else{
quill.insertEmbed(length, 'image', imgUrl)
}
// 調(diào)整光標到最后
quill.setSelection(length + 1)
//取消上傳動畫
this.quillUpdateImg = false;
},
// 上傳(文件)圖片失敗
uploadEditorError(res, file) {
console.log(res);
console.log(file);
//頁面提示
this.$message.error('上傳圖片失敗')
//取消上傳動畫
this.quillUpdateImg = false;
},
//上傳組件返回的結(jié)果
uploadResult:function (res){
this.uploadUrlPath=res;
},
openContent:function (){
console.log(this.content)
},
},
created () {
},
//只執(zhí)行一次,加載執(zhí)行
mounted () {
console.log("開始加載")
// 初始給編輯器設置title
},
watch:{
content(newVal, oldVal) {
//this.$emit('input', newVal);
console.log(newVal)
console.log(oldVal)
}
},
}
</script>
<style>
.editor {
line-height: normal !important;
height: 400px;
margin-bottom: 50px;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "請輸入鏈接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "請輸入視頻地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "標題1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "標題2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "標題3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "標題4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "標題5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "標題6";
}
.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="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "襯線字體";
}
.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: "等寬字體";
}
</style>
功能展示
文章來源地址http://www.zghlxwxcb.cn/news/detail-778786.html
到了這里,關(guān)于element ui富文本編輯器的使用(quill-editor)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!