H5內嵌富文本編輯器
微信小程序沒有支持的原生富文本組件,可以通過web-view內嵌H5實現富文本編輯功能,起初使用的是wangEditor富文本編輯器,因為項目使用的是七牛云存儲,wangEditor在pc端上傳是沒有問題的,但在在移動端調用不了本地圖片,于是換了個功能強大二次開發較強的富文本編輯器vue-quill-editor,更多請參考官方文檔, 基于此對上傳圖片進行二次開發。
七牛云 + elementUi + vue-quill-editor上傳圖片和富文本
$ npm install vue-quill-editor element-ui --save
<template> <div class="editor"> <quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" @focus="onEditorFocus($event)" @change="onEditorChange($event)"> <!-- @blur="onEditorBlur($event)" --> </quill-editor> <!-- 文件上傳input 將它隱藏--> <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="!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>
<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; //自定義邊框 outline: none; } .save_draft{ color: #B3B3B3; border-right: 1px solid #D9D9D9; } .save_release{ color: #fff; border: 1px solid #00DBD2; background: #00DBD2 } }}</style>
使用web-view組件傳遞數據的問題
小程序內嵌網頁向小程序回傳數據時,盡量不要使用路由傳參,比如富文本內容會自動截取掉src等號之后的字符串,應使用wx.miniProgram.postMessage()方法向小程序發送數據
注意:官方描述--網頁向小程序 postMessage 時,會在特定時機(小程序后退、組件銷毀、分享)觸發并收到消息
也就是說只有在小程序后退、組件銷毀、分享時才會觸發,若無效可以調換下順序就可以了
內嵌的網頁代碼:
wx.miniProgram.navigateBack({delta: 1})wx.miniProgram.postMessage({ data: '數據' })
小程序內代碼:
<web-view src="{{url}}" bindmessage="handleGetmsg"></web-view>methods = { handleGetmsg (ev) { this.data = ev.detail.data[0] this.$apply() }}
總結一下:wepy開發最多的問題就是數據緩存,組件雙向綁定最好使用twoWay: true來實現。
問題 | 原因 | 解決辦法 | 描述 |
子組件接收不到參數 | 錯誤:<component list="{{list}}"> | 正確:<component list="list"> | |
修改完布局后不刷新,必須要重新build | 將component寫到了page文件夾下導致 | 將component寫到components文件夾下 | |
使用flexbox,設置不換行顯示失效 | 必須加上新的屬性 | 加上white-space: nowrap; | 很不解,white-space: nowrap;是設置文字不換行顯示的 |
異步更新數據,不刷新 | 1.沒有使用this.$apply(); 2.傳入子組件時需要:prop.sync="data" | 1.沒有使用this.$apply(); 2.傳入子組件時需要:prop.sync="data" | |
無法多次引用同一個組件 | 同一個組件多次引用需要在components中聲明不同的id | 不使用組件,完全靠數據來管理狀態 | 完全靠數據來驅動的話,不知道對性能會不會有很大影響,待測試 |
給data中聲明的屬性賦值,如果該屬性將傳入子組件中,提示內存溢出 | 在子組件中申明的props的屬性名與傳入時的屬性名不一致 | 將傳入時的屬性名和子組件中接收的屬性名保持一致 | |
新建page或component,提示not defined | 重命名導致 | 將dist文件夾刪除,運行wepy build,重新生成dist文件夾 | |
微信授權多個權限問題 | |||
在真機上請求接口沒反應,必須開啟調試模式才行的問題 | 開發時開啟的不校驗域名配置,真機上運行除調試模式外需要域名配置 | 在微信開發平臺配置請求域名 | |
上傳圖片只能單個上傳 | 不支持多張同時上傳 | 循環上傳 | |
真機上本地圖片不顯示 | 寫components中的組件引用圖片路徑的問題 | 圖片路徑要寫使用這個組件的page的相對路徑 | |
使用wxParse后,使用autoprefixer打包報錯 | 未知 | 將wxParse.wxss改為wxParse.scss | |
input多次設值不改變的問題 | 未知 | 使用bindinput事件return值重新設置 | |
后臺接受中文參數亂碼 | 需要轉碼 | 使用encodeURI("參數")轉碼 | |
checkbox設置大小 | 使用class設置transform: scale(0.6); | ||
引用scss樣式文件報錯 | <style>標簽解析出錯 | 在<style lang="scss">中注明使用類型 | |
input設置值之后不顯示,必須獲取焦點后才會顯示,失焦后又會消失 | 設置了text-align: 'right' | 在input外層包一層view,然后為view設置固定寬度,注意不能為100% | |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答