赞
踩
- npm install vue-quill-editor --save
- npm install quill-image-drop-module --save
- npm install quill-image-resize-module --save
2.在组件下面新增组件 QlEditor
3.index.vue
- <template>
- <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"
- @blur="onEditorBlur($event)"
- @focus="onEditorFocus($event)"
- @change="onEditorChange($event)"
- >
- </quill-editor>
- </div>
- </div>
- </template>
-
- <script>
- import Vue from 'vue'
- import { Quill } from 'vue-quill-editor'
- import { ImageDrop } from 'quill-image-drop-module'
- import ImageResize from 'quill-image-resize-module'
- Quill.register('modules/imageDrop', ImageDrop)
- Quill.register('modules/imageResize', ImageResize)
-
-
- // //引入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)
-
- // //实现quill-editor编辑器拖拽上传图片
- // import Quill from 'quill'
- // import { ImageDrop } from 'quill-image-drop-module'
- // Quill.register('modules/imageDrop', ImageDrop)
-
- // //实现quill-editor编辑器调整图片尺寸
- // import ImageResize from 'quill-image-resize-module'
- // Quill.register('modules/imageResize', ImageResize)
-
- // 这里引入修改过的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 {
- name:"QlEditor",
- props: {
- /* 编辑器的内容 */
- value: {
- type: String,
- default: "",
- },
- /* 高度 */
- height: {
- type: Number,
- default: null,
- },
- /* 最小高度 */
- minHeight: {
- type: Number,
- default: null,
- },
- /* 只读 */
- readOnly: {
- type: Boolean,
- default: false,
- },
- /* 上传文件大小限制(MB) */
- fileSize: {
- type: Number,
- default: 5,
- },
- },
- model: {
- //v-model本质上是一个语法糖 这一步在父组件中可使用v-model
- prop: "value",
- event: "change",
- },
- data(){
- return {
- headers: {
- Authorization: "Bearer " + getToken(),
- token: getToken()
- },
- uploadImgUrl:process.env.VUE_APP_BASE_API + "/admin/article/uploadFile",
- uploadUrlPath:"没有文件上传",
- quillUpdateImg:false,
- content:'', //最终保存的内容
- 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('res11',res);
- console.log('file22',file);
- //拼接出上传的图片在服务器的完整地址
- let url=res.url;
- let type=url.substring(url.lastIndexOf(".")+1);
- // 获取富文本组件实例
- let quill = this.$refs.customQuillEditor.quill;
- // 获取光标所在位置
- let length = quill.getSelection().index;
- // 插入图片||视频 res.info为服务器返回的图片地址
- if(type=='mp4' || type=='MP4'){
- window.jsValue=url;
- quill.insertEmbed(length, 'video', url)
- }else{
- quill.insertEmbed(length, 'image', url)
- }
- // 调整光标到最后
- quill.setSelection(length + 1)
- //取消上传动画
- this.quillUpdateImg = false;
- },
- // 上传(文件)图片失败
- uploadEditorError(res, file) {
- //页面提示
- this.$message.error('上传图片失败')
- //取消上传动画
- this.quillUpdateImg = false;
- },
- //上传组件返回的结果
- uploadResult:function (res){
- console.log('jg',res)
- this.uploadUrlPath=res;
- },
-
- // 失去焦点事件
- onEditorBlur(quill) {
- console.log('editor blur!', quill)
- },
- // 获得焦点事件
- onEditorFocus(quill) {
- console.log('editor focus!', quill)
- },
- // 准备富文本编辑器
- onEditorReady(quill) {
- console.log('editor ready!', quill)
- },
- // 内容改变事件
- onEditorChange({ quill, html, text }) {
- console.log('editor change!', quill, html, text)
- this.content = html
- }
-
- },
- created () {
- },
- //只执行一次,加载执行
- mounted () {
- console.log("开始加载")
- // 初始给编辑器设置title
- },
- watch: {
- value: {
- handler(val) {
- if (val !== this.content) {
- this.content = val === null ? "" : val;
- }
- },
- immediate: true,
- },
- },
- }
- </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>
-

4.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)
- // 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 - 当页面加载后只载入元数据 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

5.
1、在根目录下新建vue.config.js 文件 (不是在src 下)
var webpack = require('webpack');
module.exports = {
// 在vue.config.js中configureWebpack中配置
// 要引入webpack
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
'window.Quill': 'quill/dist/quill.js',
'Quill': 'quill/dist/quill.js'
}),
]
}
}
6.main.js
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);
7.页面使用
- <el-form-item label="内容">
- <QlEditor v-model="temp.content" ref="qlEditorRef" :min-height="192"/>
- </el-form-item>
-
- <script>
- /** 提交按钮 */
- submitForm() {
- this.$refs["form"].validate(valid => {
- this.temp.content=this.$refs.qlEditorRef.content; //获取富文本的内容
- });
- },
- </script>
8.需要重新运行一下,不然会报错
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。