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; }, //上傳組件返回的結果 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使用的,上傳圖片以及頁面的訪問需要有登錄權限,所以我的上傳圖片視頻的組件里有:headers=“headers”,攜帶登錄權限
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}" rel="external nofollow" >${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文件:
<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; }, //上傳組件返回的結果 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>
功能展示
總結
到此這篇關于element ui富文本編輯器的使用效果與步驟的文章就介紹到這了,更多相關element ui富文本編輯器使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue2.X和Vue3.0數(shù)據(jù)響應原理變化的區(qū)別
這篇文章主要介紹了Vue2.X和Vue3.0數(shù)據(jù)響應原理變化的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11vue使用vue-i18n實現(xiàn)國際化的實現(xiàn)代碼
本篇文章主要介紹了vue使用vue-i18n實現(xiàn)國際化的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04element vue validate驗證名稱重復 輸入框與后臺重復驗證 特殊字符 字符長度 及注意事項小結【實例代碼
這篇文章主要介紹了element vue validate驗證名稱重復 輸入框與后臺重復驗證 特殊字符 字符長度 及注意事項小結,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2018-11-11