微信小程序没有支持的原生富文本组件,可以通过web-view内嵌H5实现富文本编辑功能,起初使用的是wangEditor富文本编辑器,因为项目使用的是七牛云存储,wangEditor在pc端上传是没有问题的,但在在移动端调用不了本地图片,于是换了个功能强大二次开发较强的富文本编辑器vue-quill-editor,更多请参考官方文档, 基于此对上传图片进行二次开发。
七牛云 + elementUi + vue-quill-editor上传图片和富文本
$ npm install vue-quill-editor element-ui --save
<template> <div> <quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" @focus="onEditorFocus($event)" @change="onEditorChange($event)"> <!-- @blur="onEditorBlur($event)" --> </quill-editor> <!-- 文件上传input 将它隐藏--> <el-upload :action="qnLocation" :before-upload='beforeUpload' :data="uploadData" :on-success='upScuccess' ref="upload"> <el-button size="small" type="primary" v-loading.fullscreen.lock="fullscreenLoading"> </el-button> </el-upload> <div> <button @click="handleCancel">取消</button> <button @click="handleSubmit" :disabled="!content">确定</button> </div> </div> </template> <script> import Quill from 'quill' import api from '@/request/api' import Cookies from 'js-cookie' const DOMAIN = 'https://img.makeapoint.info/' export default { name: 'qillEditor', computed: { editor() { return this.$refs.myQuillEditor.quill } }, created () { this.$nextTick(() => { if (this.$route.query.content) { this.content = this.$route.query.content this.tempRichText = this.content } let token = this.$route.query.currentToken Cookies.set('currentToken_mini', token) }) }, mounted () { this.$refs.myQuillEditor.quill.getModule('toolbar').addHandler('image', this.imgHandler) }, data () { return { qnLocation: 'https://up-z2.qbox.me', uploadData: {}, // 上传参数 fullscreenLoading: false, addRange: [], uploadType: '', // 上传的文件类型 content: '', // 提交的富文本内容 tempRichText: '', // 临时富文本内容 editorOption: { // 自定义菜单 placeholder: "请输入游记正文", modules: { toolbar: [ // ['bold', 'italic', 'underline', 'strike'], // [{ 'header': 1 }, { 'header': 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] }], // 标题 // [{ 'font': [] }], // 字体 [{ 'color': [] }, { 'background': [] }], [{ 'align': [] }], ['blockquote'], ['link', 'image'], ['clean'] ] } } } }, methods: { handleCancel () { // 回退至小程序 window.wx.miniProgram.navigateBack({ delta: 1 }) window.wx.miniProgram.postMessage({ // 向小程序发送数据 data: this.tempRichText }) }, handleSubmit () { // 返回小程序并提交富文本内容 window.wx.miniProgram.navigateBack({ delta: 1 }) window.wx.miniProgram.postMessage({ // 向小程序发送数据 data: this.content }) }, // 图片上传前获得数据token数据 qnUpload (file) { this.fullscreenLoading = true const suffix = file.name.split('.') const ext = suffix.splice(suffix.length - 1, 1)[0] return api.upload().then(res => { this.uploadData = { key: `image/${suffix.join('.')}_${new Date().getTime()}.${ext}`, token: res.data.data } }) }, // 图片上传之前调取的函数 beforeUpload (file) { return this.qnUpload(file) }, // 图片上传成功回调插入到编辑器中 upScuccess (e, file, fileList) { this.fullscreenLoading = false let url = '' url = DOMAIN + e.key if (url != null && url.length > 0) { // 将文件上传后的URL地址插入到编辑器文本中 let value = url this.addRange = this.$refs.myQuillEditor.quill.getSelection() // 调用编辑器的 insertEmbed 方法,插入URL this.$refs.myQuillEditor.quill.insertEmbed(this.addRange !== null ? this.addRange.index : 0, this.uploadType, value, Quill.sources.USER) } this.$refs['upload'].clearFiles() // 插入成功后清除input的内容 }, // 点击图片icon触发事件 imgHandler(state) { this.addRange = this.$refs.myQuillEditor.quill.getSelection() if (state) { let fileInput = document.getElementById('imgInput') fileInput.click() // 加一个触发事件 } this.uploadType = 'image' }, // 点击视频icon触发事件 // videoHandler(state) { // this.addRange = this.$refs.myQuillEditor.quill.getSelection() // if (state) { // let fileInput = document.getElementById('imgInput') // fileInput.click() // 加一个触发事件 // } // this.uploadType = 'video' // }, // onEditorBlur(editor) { // this.content = html // }, // 编辑器获得光标 onEditorFocus(editor) { editor.enable(true) }, // 编辑器文本发生变化 onEditorChange({ editor, html, text }) { this.content = html } } } </script>