這是《基於nuxt和iview搭建OM後臺管理系統實踐》這一個系列文章的目錄,大體思路以下:css
上一篇簡要介紹了一下這個項目的項目背景,從這一篇開始我會寫開發公共組件的過程,這一篇講解一下富文本編輯器quill的集成吧。html
如動圖所示,爲後臺管理系統添加內容的功能頁面,能夠看到已經集成了上傳圖片組件和富文本編輯器組件。
前端
這個富文本集成了quill這個開源庫 [[quill中文文檔]](https://github.com/BingKui/Qu...。在vue-cli構建的項目中直接引用quill的包一點問題都沒有,可是我用的nuxt.js是基於服務端渲染的,多數狀況下會報下面這個錯誤:vue
window is not defined
這是由於window對象只存在於瀏覽器端,服務端渲染的時候是不存在window對象的。那麼我應該怎麼作呢??ios
我仍是直接上代碼吧:git
// 文件plugins/nuxt-quill-plugins.js import Vue from 'vue' // import VueQuillEditor from 'vue-quill-editor' // Vue.use(VueQuillEditor) 直接引用會報錯 if (process.browser) { //加一個瀏覽器端判斷,只在瀏覽器端才渲染就不會報錯了 const VueQuillEditor = require('vue-quill-editor/dist/ssr') Vue.use(VueQuillEditor) }
//文件nuxt.config.js,省略其餘代碼 plugins: [ '~plugins/iview-ui', '~plugins/qs', '~plugins/urlencode', {src: '~plugins/nuxt-quill-plugin.js',ssr: false} ],
//文件 components/full-editor.vue <template> <section class="container"> <!-- <form id="uploadForm"> --> <input class="file" type="file" style="display:none" id="file" ref="input" @change="doUpload"> <!-- </form> --> <div class="quill-editor" ref="myQuillEditor" :content="content" @change="onEditorChange($event)" @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @ready="onEditorReady($event)" v-quill:myQuillEditor="editorOption"> </div> </section> </template> <script> import {qiniuConfig,quillEditorConfig} from '~/config';//七牛上傳和富文本toolbar配置文件 const QiniuUPToken = require('qiniu-uptoken');//前端生成七牛上傳token import axios from '~/plugins/axios'; export default { name: "full-editor", head() { return { link: [ { href: "/full-editor/quill.core.css", rel: "stylesheet" }, { href: "/full-editor/quill.snow.css", rel: "stylesheet" }, { href: "/full-editor/quill.bubble.css", rel: "stylesheet" } ] }; }, data() { const self = this; return { content: "", editorOption: { // some quill options modules: { toolbar: { container:quillEditorConfig.toolbarOptions, handlers:{ 'image':function(){ // console.log(this) this.quill.format('image', false);//禁用quill內部上傳圖片方法 self.imgHandler(this) } } }, }, placeholder: '請輸入信息', theme: "snow", quill:'' } }; }, mounted() { // console.log("app init"); }, methods: { onEditorBlur(editor) { // console.log("editor blur!", editor); }, onEditorFocus(editor) { // console.log("editor focus!", editor); }, onEditorReady(editor) { // console.log("editor ready!", editor); }, onEditorChange({ editor, html, text }) { // console.log("editor change!", editor, html, text); this.content = html; this.$emit('editorContent',html) // console.log(this.content); }, imgHandler(handle){ this.quill = handle.quill; var inputfile = document.getElementById('file'); inputfile.click(); }, doUpload(){ let files = document.getElementById('file'); // console.log(files.files[0]); let uptoken = QiniuUPToken(qiniuConfig.access_key,qiniuConfig.secret_key,qiniuConfig.bucketname) // console.log(uptoken); this.qiniuUpload(files.files[0],uptoken); }, qiniuUpload(file, token){ let param = new FormData(); //建立form對象 param.append('file',file,file.name);//經過append向form對象添加數據 param.append('token',token);//添加form表單中其餘數據 // console.log(param. `get('file')); //FormData私有類對象,訪問不到,能夠經過get判斷值是否傳進去 let config = { headers:{'Content-Type':'multipart/form-data'} }; //添加請求頭 axios.post(qiniuConfig.action_url,param,config) .then(res=>{ // console.log(res); // console.log(this.quill); let length = this.quill.getSelection().index; const imgUrl = qiniuConfig.pic_hostname+res.key;//插入上傳的圖片 this.quill.insertEmbed(length, 'image', imgUrl); // this.quill.insertEmbed(index, 'image', imgUrl);//插入上傳的圖片 // console.log(res.data); }) .then((err)=>{ // console.log(err) }) } } }; </script> <style scoped> .container { width: 100%; margin: 0 auto; /* padding: 10px 0; */ } .quill-editor { min-height: 200px; max-height: 400px; overflow-y: auto; } </style>
封裝組件須要注意的幾個點:github
<script> export default { head() { return { link: [ { href: "/full-editor/quill.core.css", rel: "stylesheet" }, { href: "/full-editor/quill.snow.css", rel: "stylesheet" }, { href: "/full-editor/quill.bubble.css", rel: "stylesheet" } ] }; }, } </script>
// 文件config/index.js /** * @description 富文本編輯器quill的配置文件 * @argument 參考文檔https://sheweifan.github.io/2018/01/07/nuxt-quill-qiniu/ * @argument quill中文文檔https://github.com/BingKui/QuillChineseDoc/blob/master/SUMMARY.md */ export const quillEditorConfig = { toolbarOptions:[ ["bold", "italic", "underline", "strike"], // 切換按鈕 ["blockquote", "code-block"], // [{ 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] }], [{ color: [] }, { background: [] }], // 主題默認下拉,使用主題提供的值 [{ font: [] }], [{ align: [] }], ['image'],//上傳圖片 ['video'],//視頻 ["clean"] // 清除格式 ] }
// 父組件 <template> <div class="body"> <full-editor ref="myFullEditor" v-model="formItem.body" @editorContent="editorContent" > </full-editor> </div> </template> <script> const fullEditor = () => import("@/components/full-editor"); export default { layout: "nav", components: { fullEditor }, mounted() { this.loadData();//加載數據 this.$refs.myFullEditor.content = this.body;//父組件給富文本編輯器傳遞值 } } </script>
封裝一個富文本組件,開始作以前覺得會蠻容易的,覺得就引用一下就就能夠了,沒想到會遇到以上的那些坑,最終在百度和翻閱github後很好的解決了問題,最終也封裝完成也知足了需求,後續我會找個時間剔除一些業務代碼把組件放到github上。vue-cli