H5 embedded rich text editor

Wechat applet does not support native rich text components, so rich text editing functions can be realized through web-view embedded H5. At first, the wangEditor rich text editor is used, because the project uses Qiniu Cloud storage, there is no problem with wangEditor uploading on PC side, but it cannot call local pictures on mobile side. So I changed to a powerful rich text editor vue-quill-editor for secondary development. For more information, please refer to the official document. Based on this, I carried out secondary development for uploaded pictures.

Uploads images and rich text to elementUi + vue-quill-editor

$ npm install vue-quill-editor element-ui --save
Copy the code
<template> <div class="editor"> <quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" @focus="onEditorFocus($event)" @change="onEditorChange($event)"> <! -- @blur="onEditorBlur($event)" --> </quill-editor> <! <el-upload class="upload-demo" :action="qnLocation" :before-upload='beforeUpload' --> <el-upload class="upload-demo" :action="qnLocation" :before-upload='beforeUpload' :data="uploadData" :on-success='upScuccess' ref="upload" style="display:none"> <el-button size="small" type="primary" id="imgInput" v-loading.fullscreen.lock="fullscreenLoading"> </el-button> </el-upload> <div class="btn_box flex"> <button class="flex-1 save_draft" @click="handleCancel"> </button> <button class="flex-1 save_release" @click="handleSubmit" :disabled="! </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: '', // uploadType: '', // uploadType: '', // uploadType: '', // {// placeholder: modules: {toolbar: [// ['bold', 'italic', 'underline', 'strike'], // [{'header': 1 }, { 'header': 2 }], [{ 'list': 'ordered' }, { 'list': 'bullet' }], // [{ 'script': 'sub' }, { 'script': 'super'}], / / [{' text-indent: '1'}, {' text-indent: '+ 1'}], / / indentation / / [{' direction ':' RTL}], / / reverse / / [{' size: [' small 'false,' large 'and' huge ']}], / / / / font size [{' header ': [1, 2, 3, 4, 5, 6, false]}], / / title / / [{' font' : []}], / / font [{' color: []}, {' background: []}], [{' align: [] }], ['blockquote'], ['link', 'image'], ['clean'] ] } } } }, methods: {handleCancel () {/ / back to the small program window. The wx. MiniProgram. NavigateBack ({delta: 1}) window. Wx. MiniProgram. PostMessage ({/ / send data to the small program data: Enclosing tempRichText})}, handleSubmit () {/ / return small application and submit the rich text contents window. Wx. MiniProgram. NavigateBack ({delta: 1}) window. Wx. MiniProgram. PostMessage ({/ / send data to the small program data: this.content }) }, 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}})}, // Call functions before uploading images. 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) {// Insert the url of the uploaded file into the editor text let value = url this.addrange = This. $refs. MyQuillEditor. Quill. GetSelection () / / call the editor insertEmbed method, Insert the URL enclosing $refs. MyQuillEditor. Quill. InsertEmbed (enclosing addRange! == null ? this.addRange.index : 0, this. UploadType, value, quill.sources.user)} this.$refs['upload']. / / click on the image icon trigger imgHandler (state) {this. AddRange = this. $refs. MyQuillEditor. Quill. GetSelection () if (state) {let FileInput = document.getelementById ('imgInput') fileInput.click()} this.uploadType = 'image'}, / / / / video click the icon to trigger events videoHandler (state) {/ / this. AddRange = this. $refs. MyQuillEditor. Quill. GetSelection () / / if (state) {// let fileInput = document.getelementById ('imgInput') // fileInput.click() // add a trigger event // // this.uploadType = 'video' // }, // onEditorBlur(editor) { // this.content = html // }, OnEditorFocus (editor) {editor.enable(true)}, onEditorChange({editor, HTML, text }) { this.content = html } } } </script>Copy the code
<style lang="less"> .quill-editor { .ql-container { min-height: 50vh; } } .ql-editor img { width: 100%; height: 200px; } </style> <style lang="less" scoped> .editor { width: 100%; height: 100vh; .flex { display: flex; } .flex-1 { flex: 1; } .btn_box { position: fixed; bottom: 0; left: 0; width: 100%; height: 50px; line-height: 50px; z-index: 999; background: #FAFAFA; Box-shadow :0px 1px 0px 0px Rgba (217,217,217,0.5); border-top: 1px solid #D9D9D9; text-align: center; button { font-size: 16px; line-height: 50px; margin: 0; padding: 0; border: 1px solid #D9D9D9; // Custom border outline: none; } .save_draft{ color: #B3B3B3; border-right: 1px solid #D9D9D9; } .save_release{ color: #fff; border: 1px solid #00DBD2; background: #00DBD2 } } } </style>Copy the code

useweb-viewA problem with the component passing data

Applet embedded web pages to the small program back data, try not to use routing parameter, such as rich text content will automatically intercept out SRC = “string, should use wx. MiniProgram. PostMessage () method to the small program to send data

Note: Official description – When a web page is sent to the applet postMessage, it will trigger and receive a message at certain moments (applet back, component destruction, share)

This means that it can only be triggered when the applet is backtracked, the component is destroyed, or shared. If it does not work, the order can be reversed

Embedded page code:

wx.miniProgram.navigateBack({delta: 1})
wx.miniProgram.postMessage({ data: 'data' })
Copy the code

Code in applets:

<web-view src="{{url}}" bindmessage="handleGetmsg"></web-view>
Copy the code
methods = {
    handleGetmsg (ev) {
      this.data = ev.detail.data[0]
      this.$apply()
    }
}
Copy the code

In summary: One of wepy’s most developed problems is data caching, and component bidirectional binding is best implemented using twoWay: True.