首先我使用的富文本编辑器是vue-quill-editor
排序使用图片拖动来排序使用vuedraggable
组件库用的Ant Design Vue
使用npm进行下载
npm install vue-quill-editor --save
npm i vuedraggable --save
当然也可以按照官方的方法下载,到官方
因为我是在原有老项目上开发的使用的组件库是ant-design-vue 1x版,当然使用其他组件库也可以
然后还有重要的一步需要引入jquery后面有地方需要用到(后面因为找到更好的方法不引入也可以)
使用npm进行下载jquery
npm install jquery --save;
下面直接上代码
<template>
<div>
<quill-editor :ref="toref" v-model="content" :options="editorOption" />
<a-modal
title="上传图片(拖动图片排序)"
:visible="visible"
@ok="handleOk"
@cancel="visible = false"
>
<div style="max-height: 70vh;overflow-y: auto;">
<draggable
v-model="loginimageUrlbig"
filter=".forbid"
group="people"
@change="change"
@start="start"
:move="onMove"
class="grid-container"
style="display: flex;flex-wrap: wrap;"
@end="end">
<div class="cyimagea" :class="index==0?'forbid':''" v-for="(item,index) in loginimageUrlbig" :key="index">
<a-icon v-if="item!=''" type="close-circle" class="cyicon" @click="deleteimg(index)" />
<a-upload list-type="picture-card" class="avatar-uploader" :show-upload-list="false" :multiple="true"
:data="headerdata" action="https://upload-cn-east-2.qiniup.com"
:before-upload="beforeUploadlogin" @change="handleChangeloginbig">
<div v-if="index<9">
<img v-if="item!=''" style="width:100px;height:100px;" :src="item" alt="avatar" />
<div v-else style="margin-top:0px">
<a-icon type="plus" />
</div>
</div>
</a-upload>
</div>
</draggable>
</div>
</a-modal>
</div>
</template>
<script>
const titleConfig = [
{ Choice: '.ql-insertMetric', title: '跳转配置' },
{ Choice: '.ql-bold', title: '加粗' },
{ Choice: '.ql-italic', title: '斜体' },
{ Choice: '.ql-underline', title: '下划线' },
{ Choice: '.ql-header', title: '段落格式' },
{ Choice: '.ql-strike', title: '删除线' },
{ Choice: '.ql-blockquote', title: '块引用' },
{ Choice: '.ql-code', title: '插入代码' },
{ Choice: '.ql-code-block', title: '插入代码段' },
{ Choice: '.ql-font', title: '字体' },
{ Choice: '.ql-size', title: '字体大小' },
{ Choice: '.ql-list[value="ordered"]', title: '编号列表' },
{ Choice: '.ql-list[value="bullet"]', title: '项目列表' },
{ Choice: '.ql-direction', title: '文本方向' },
{ Choice: '.ql-header[value="1"]', title: 'h1' },
{ Choice: '.ql-header[value="2"]', title: 'h2' },
{ Choice: '.ql-align', title: '对齐方式' },
{ Choice: '.ql-color', title: '字体颜色' },
{ Choice: '.ql-background', title: '背景颜色' },
{ Choice: '.ql-image', title: '图像' },
{ Choice: '.ql-video', title: '视频' },
{ Choice: '.ql-link', title: '添加链接' },
{ Choice: '.ql-formula', title: '插入公式' },
{ Choice: '.ql-clean', title: '清除字体格式' },
{ Choice: '.ql-script[value="sub"]', title: '下标' },
{ Choice: '.ql-script[value="super"]', title: '上标' },
{ Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
{ Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
{ Choice: '.ql-header .ql-picker-label', title: '标题大小' },
{ Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
{ Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
{ Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
{ Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
{ Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
{ Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
{ Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
{ Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
{ Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
{ Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
{ Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
{ Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
]
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
];
import API from "@/Api/index.js";
import UNITY from "@/commont/user.js";
import draggable from "vuedraggable";
import * as Quill from 'quill';
export default {
components: {
draggable
},
props:{
//这里一定要传值的随便一个值都行,不然给图片换取位置然后点击确定时会报错。
toref: {
type: String,
default:"quillEditor"
},
},
data() {
return {
content: "",
headerdata: {
token: "",
key: "",
},
loginimageUrlbig: [],
URL: "",
cyloginimageUrlbig: [],
editorOption: {
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
// 重写点击组件上的图片按钮要执行的代码这里用到了jquery
'image': (value) => {
this.visible=true
}
}
}
}
},
cyput: 0
}
},
created() {
},
mounted() {
this.initTitle()// 富文本操作提示词
//文本集中-富文本本来是靠clss完成文字居中的,换成style这样可以在其他没引入quill-editor组件的项目正确展示
var fontSizeStyle = Quill.import('attributors/style/size')
fontSizeStyle.whitelist = ['12px','14px','16px','20px','24px','36px']
Quill.register(fontSizeStyle, true)
var Align = Quill.import('attributors/style/align');
Align.whitelist = ['right','center','justify'];
Quill.register(Align, true);
},
methods: {
monitoring(){
this.$on('childMethod', (item) => {
return item = this.content
})
},
chumonitoring(){
this.$on('chuchildMethod', (item) => {
this.content=item
})
},
async beforeUploadlogin(file) {
this.cyput++
let that = this;
let time = new Date().getTime();
time = time + '' + that.cyput
//获取七牛云token
await API.UPLOADUPLOADTOKEN().then(res => {
that.headerdata.token = res.data.data.token;
that.headerdata.key = "permanent/head/" + time + '.png';
that.URL = UNITY.getSession("qiniu_cdnurl");//获取图片的前缀
that.cyarr.push(that.headerdata.key)
})
},
handleChangeloginbig(info) {
if (info.file.status === "uploading") {
return;
}
if (info.file.status === "done") {
if (this.loginimageUrlbig.length < 9) {
if (this.loginimageUrlbig[0] != "") {
this.loginimageUrlbig.unshift("")
}
} else {
this.loginimageUrlbig.shift()
}
let loCbig = this.URL + '/' + info.file.response.key;
this.loginimageUrlbig.push(loCbig)
}
},
handleOk(){
// 获取文本编辑器
let toeval = "this.$refs."+this.toref+".quill"
let quill = eval(toeval);
this.$nextTick(()=>{
this.loginimageUrlbig.forEach((item,indexa)=>{
if(indexa!=0){
let loCbig = item
if (loCbig) {
this.$nextTick(()=>{
// 获取光标位置
let length = quill.selection.savedRange.index;
// 插入图片到光标位置
quill.insertEmbed(length, "image",loCbig);
quill.setSelection(length + 1);
})
} else {
this.$essage.error('图片插入失败')
}
}
})
this.visible=false
this.loginimageUrlbig=['']
})
},
// 监听拖拽
change(event) {
},
// 开始拖拽
start(event) {
},
onMove(e){
if (e.relatedContext.index == 0) return false;
return true;
},
// 结束拖拽
end(event) {
},
// 删除图片
deleteimg(index) {
let that = this;
that.loginimageUrlbig.splice(index, 1)
if (that.loginimageUrlbig.length < 9) {
if (that.loginimageUrlbig[0] != "") {
that.loginimageUrlbig.unshift("")
}
}
},
// 富文本操作提示词
initTitle () {
document.getElementsByClassName('ql-editor')[0].dataset.placeholder = ''
for (let item of titleConfig) {
let tip = document.querySelector('.quill-editor ' + item.Choice)
if (!tip) continue
tip.setAttribute('title', item.title)
}
},
}
}
</script>
<style scoped>
.cyimagea {
margin-bottom: 10px;
position: relative;
width: 140px;
height: 120px;
}
.cyicon{
position: absolute;
right: 0;
}
.avatar-uploader {
width: 100px;
height: 100px;
margin-top: 10px;
}
</style>
最后的效果会按照图片顺序排列在富文本框