這是《基於nuxt和iview搭建OM後臺管理系統實踐》這一個系列文章的目錄,大體思路以下:css
上一篇簡要介紹了一下這個項目的項目背景,從這一篇開始我會寫開發公共組件的過程,這一篇講解一下富文本編輯器quill的集成吧。html
如動圖所示,爲後臺管理系統添加內容的功能頁面,能夠看到已經集成了上傳圖片組件和富文本編輯器組件。 前端
這個富文本集成了quill這個開源庫 [quill中文文檔]。在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
如下爲本系列的文章合集,在此列出便於查閱:axios