安装方法:npm install -d vue-quill-editor quill vue-cropper
官网:
vue-quill-editor:https://quilljs.com/
git:https://github.com/surmon-china/vue-quill-editor
vue-cropper:https://github.com/xyxiao001/vue-cropper
nuxt框架基于vue的服务端渲染,有报错 Document / Window not defined 的问题,使用富文本编辑器进行组件单独引入的时候会报错,在组件中使用
1 2 3 |
if (process.client) { require('external_library') } |
之后element会显示不出来,所以在使用这种引入插件的时候建议直接在
plugins文件夹内直接全局注册,使用服务器渲染
1 2 3 4 5 6 7 |
plugins: [ '@/plugins/element-ui', '@/plugins/bootstrap-vue', { src: '@/plugins/map', ssr: false }, { src: '@/plugins/vue-quill-editor', ssr: false }, { src: '@/plugins/vue-cropper', ssr: false } ], |
组件使用代码:(网上摘取)
在使用上传的时候action是传输一个链接地址,如果想根据自己定义的axios上传需要添加一个auto-upload=”false”意思不取消自动上传更据:on-change=”onChange”(文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用)动作进行上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
<template> <div> <!-- 图片上传组件--> <el-upload :before-upload="beforeUpload" :show-file-list="false" accept="image/*" action="" class="avatar-uploader" hidden name="file" type='file'> <el-button size="small" type="primary">点击上传图片 到 文本编辑器</el-button> </el-upload> <!-- 编辑器组件--> <quill-editor :options="editorOption" @change="onEditorChange($event)" class="editor" ref="myQuillEditor" v-model="content"> </quill-editor> <!-- 图片裁剪组件--> <el-dialog :visible.sync="isShowCropper" top="5vh"> <VueCropper :autoCrop="option.autoCrop" :autoCropHeight="option.autoCropHeight" :autoCropWidth="option.autoCropWidth" :canScale="option.canScale" :fixed="option.fixed" :fixedNumber="option.fixedNumber" :img="option.img" :info="option.info" :outputSize="option.outputSize" :outputType="option.outputType" ref="cropper" style="height:600px;margin:20px 0" > </VueCropper> <br/> <el-button @click="onCubeImg()" type="primary">生成图片</el-button> <el-button @click="isShowCropper = false">取消</el-button> </el-dialog> </div> </template> <script> // 富文本工具栏配置 const toolbarOptions = [ ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线 ['blockquote', 'code-block'], // 引用 代码块 [{ header: 1 }, { header: 2 }], // 1、2 级标题 [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表 [{ script: 'sub' }, { script: 'super' }], // 上标/下标 [{ indent: '-1' }, { indent: '+1' }], // 缩进 // [{'direction': 'rtl'}], // 文本方向 [{ size: ['small', false, 'large', 'huge'] }], // 字体大小 [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题 [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色 [{ font: [] }], // 字体种类 [{ align: [] }], // 对齐方式 ['clean'], // 清除文本格式 ['link', 'image', 'video'] // 链接、图片、视频 ] import 'quill/dist/quill.core.css' import 'quill/dist/quill.snow.css' import 'quill/dist/quill.bubble.css' import { uImage } from '@/api/uploadImage.js' export default { name: 'textEditor', components: {}, props: { /*编辑器的内容*/ value: { type: String }, /*图片大小*/ maxSize: { type: Number, default: 4000 //kb } }, data() { return { // 富文本数据 content: '', quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示 editorOption: { theme: 'snow', // or 'bubble' placeholder: '请输入您想输入的内容', modules: { toolbar: { container: toolbarOptions, // 和上传按钮进行绑定 handlers: { image: function(value) { console.log(value) if (value) { // 触发input框选择图片文件 document.querySelector('.avatar-uploader input').click() } else { this.quill.format('image', false) } } } } } }, // 切图器数据 option: { img: '', // 裁剪图片的地址 info: true, // 裁剪框的大小信息 outputSize: 1, // 裁剪生成图片的质量 outputType: 'png', // 裁剪生成图片的格式 canScale: true, // 图片是否允许滚轮缩放 autoCrop: true, // 是否默认生成截图框 autoCropWidth: 150, // 默认生成截图框宽度 autoCropHeight: 150, // 默认生成截图框高度 fixed: true, // 是否开启截图框宽高固定比例 fixedNumber: [4, 4] // 截图框的宽高比例 }, isShowCropper: false, isClient: true, width: '150px', height: '150px' } }, methods: { // 上传切图前调用 beforeUpload(file) { /** * URL.createObjectURL(file)生成本地的url * 返回false终止了自动上传 * */ this.option.img = URL.createObjectURL(file) this.option.autoCropWidth = this.width this.option.autoCropHeight = this.height this.isShowCropper = true return false }, // 确定裁剪图片 onCubeImg() { // 获取cropper的截图的base64 数据data this.$refs.cropper.getCropData(data => { //截取bas64 截取base64的格式 和 图片的后缀名 let baseSplit= data.split(',') let format = baseSplit[0].split('/')[1].split(';')[0] //获取base64格式的信息 let base = '' if (process.client) { base = window.atob(baseSplit[1]) } //转格式:base64转图片 /** *格式为:File * lastModified: 1593134876792 * lastModifiedDate: Fri Jun 26 2020 09:27:56 GMT+0800 (中国标准时间) {} * name: "img.png" * size: 15407 * type: "image/png" * webkitRelativePath: "" * */ let index = base.length let u8arr = new Uint8Array(index) while (index--) { u8arr[index] = base.charCodeAt(index) } let blods = new File([u8arr],'img.' + format,{type: 'image/' + format }) /** * 建立一个formData表单,之后把上面的base64转换后的格式使用append传递给FormData * */ let fromData = new FormData() fromData.append('file',blods) this.$notify({ title: '成功', message: '正在上传中', type: 'success' }); //发出网络请求 uImage(fromData).then(res => { this.$notify({ title: '成功', message: '图片上传成功', type: 'success' }); // 获取富文本组件实例 let quill = this.$refs.myQuillEditor.quill if(res.code === 200){ // 获取光标所在位置 /** * quill.insertEmbed(length, 'image', res.data.url) * 图片显示的位置,根据length后的位置显示 * */ if (quill.getSelection() && quill.getSelection().index) { let length = quill.getSelection().index quill.insertEmbed(length, 'image', res.data.url) } else { let length = 0 quill.insertEmbed(length, 'image', res.data.url) } // 调整光标到最后 quill.setSelection(length + 1) }else { console.log(res.data.code) this.$notify({ title: '警告', message: '图片上传失败', type: 'warning' }); } this.isShowCropper = false // 先将显示图片地址清空,防止重复显示 this.option.img = '' }) }) }, onEditorChange() { console.log(this.content) //富文本内容改变事件 发送给父级元素 this.$emit('change', this.content) } }, mounted() { setTimeout(() => { this.content = this.value }, 500) } } </script> <style lang="scss"> </style> |