vue背景管理系統富文本元件(一)tinymce
簡介
富文本元件作為背景管理系統的最重要的基礎元件之一,一定要選擇坑比較少的富文本廠家。這裡使用的是好看又坑少的tinymce。
主要依賴說明 (先安裝,步驟略)
{
"axios": "^0.18.0",
"element-ui": "2.11.1",
"vue": "^2.6.10",
"vue-router": "^3.0.1"
}
tinymce:5.0.8 這裡直接采用下載下傳源碼的方式,npm下載下傳極大的影響打包速度,也可以使用cdn
tinymce官網下載下傳位址
正文
1.下載下傳tinymce源碼放在vue-cli 3生成的 public檔案夾下的static檔案夾下 ,如圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmLwYDOyEDMzYTMzIDOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
需要語言包的話,單獨下載下傳zh_CN.js檔案放在tinymce_5.0.8檔案夾下的lang檔案夾下
zh_CN.js官網下載下傳位址
2.在入口html檔案中導入
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<meta name="description" content="<%= webpackConfig.name %>" />
<meta name="robots" content="noindex,nofollow,noarchive" />
<title>title</title>
</head>
<body>
<script src="<%= BASE_URL %>static/tinymce_5.0.8/tinymce.min.js"></script>
<div id="app"></div>
</body>
</html>
3.元件Tinymce
檔案目錄
src/components/Tinymce/index.vue
<template>
<div class="tinymce-container editor-container" :class="{fullscreen:fullscreen}">
<textarea :id="tinymceId" class="tinymce-textarea" />
<div class="editor-custom-btn-container">
<multiple-upload class="editor-upload-btn" @success="imageSuccess" />
</div>
</div>
</template>
<script>
import axios from 'axios'
// MultipleUpload元件見 https://blog.csdn.net/qq_39953537/article/details/100039094
import MultipleUpload from '@/components/MultipleUpload'
import plugins from './plugins' // 見下文
import toolbar from './toolbar' // 見下文
// 上傳html片段接口根據自己項目更換
import { uploadHtml } from '@/api/upload'
export default {
name: 'Tinymce',
components: {
MultipleUpload
},
props: {
// 預設填充到富文本的html檔案
html: {
type: String,
default: ''
},
toolbar: {
type: Array,
default() {
return []
}
},
menubar: {
type: Boolean,
default: false
},
height: {
type: Number,
default: 400
}
},
data() {
return {
hasChange: false,
hasInit: false,
tinymceId: 'vue-tinymce-' + +new Date(),
fullscreen: false,
value: '',
editorContent: ''
}
},
watch: {
value(val) {
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || '')
)
},
html(val) {
if (this.isUrl) {
this.loadUrl(val)
}
}
},
created() {
if (this.html && this.html.startsWith('http')) {
this.loadUrl(this.html)
} else {
this.value = this.html + ''
this.editorContent = this.html + ''
}
},
mounted() {
this.initTinymce()
},
activated() {
this.initTinymce()
},
deactivated() {
this.destroyTinymce()
},
destroyed() {
this.destroyTinymce()
},
methods: {
initTinymce() {
window.tinymce.init({
fontsize_formats: '12px 14px 16px 18px 20px 24px 36px',
language: 'zh_CN',
language_url: '/static/tinymce_5.0.8/langs/zh_CN.js',
selector: `#${this.tinymceId}`,
height: this.height,
body_class: 'panel-body ',
object_resizing: true,
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
menubar: this.menubar,
plugins: plugins,
end_container_on_empty_block: true,
powerpaste_word_import: 'clean',
code_dialog_height: 450,
code_dialog_width: 1000,
advlist_bullet_styles: 'square',
advlist_number_styles: 'default',
default_link_target: '_blank',
link_title: false,
init_instance_callback: editor => {
if (this.value) {
editor.setContent(this.value)
}
this.hasInit = true
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true
this.$emit('input', editor.getContent())
this.editorContent = editor.getContent()
})
},
setup(editor) {
editor.on('FullscreenStateChanged', e => {
this.fullscreen = e.state
})
}
})
},
destroyTinymce() {
if (window.tinymce.get(this.tinymceId)) {
window.tinymce.get(this.tinymceId).destroy()
}
},
loadUrl(url) {
if (url && url.length > 0) {
axios
.get(url)
.then(response => {
// 處理HTML顯示
this.value = response.data
this.editorContent = response.data
this.$emit('subLoadUrlToHtml', response.data)
this.$emit('input', response.data)
})
.catch(() => {
this.value = '伺服器資料加載失敗,請重試!'
})
}
},
// 設定編輯器内容
setContent(value) {
window.tinymce.get(this.tinymceId).setContent(value)
},
// 擷取編輯器内容
getContent() {
window.tinymce.get(this.tinymceId).getContent()
},
// 圖檔上傳成功後填充到富文本編輯器
async imageSuccess(urlList) {
try {
let imageTemplateList = ''
urlList.forEach(item => {
const image = `<img style="max-width:100%;" src="${item}">`
imageTemplateList = imageTemplateList + image
})
window.tinymce.get(this.tinymceId).insertContent(imageTemplateList)
this.$message({
message: '上傳成功!',
type: 'success'
})
} catch (error) {
console.log(error)
this.$message({
message: error,
type: 'error'
})
}
},
// 編輯器内容上傳到cos,調用傳回url
async content2Url() {
try {
const res = await uploadHtml(this.editorContent)
return res
} catch (error) {
this.$message({
message: error.data.message,
type: 'error'
})
}
}
}
}
</script>
<style lang='scss' >
#tinymce {
background-color: blue;
p {
margin: 0;
}
}
.tinymce-container {
position: relative;
}
.tinymce-container >>> .mce-fullscreen {
z-index: 10000;
}
.tinymce-textarea {
visibility: hidden;
z-index: -1;
}
.editor-custom-btn-container {
position: absolute;
right: 4px;
top: 4px;
/*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
z-index: 10000;
position: fixed;
}
.editor-upload-btn {
display: inline-block;
}
// 隐藏底部logo欄
.mce-edit-area + .mce-statusbar {
opacity: 0;
height: 0;
}
</style>
src/components/Tinymce/plugins.js
const plugins = [
'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount paste'
]
export default plugins
src/components/Tinymce/toolbar.js
const toolbar = ['formatselect fontsizeselect forecolor backcolor bold italic underline strikethrough alignleft aligncenter alignright outdent indent removeformat hr undo redo']
export default toolbar
4.使用
<template>
<div>
<tinymce
ref="tinymce"
:height="500"
:html="html"
@input="getContent"
/>
</div>
</template>
<script>
import AppCropper from '@/components/Cropper'
export default {
name: 'GoodsForm',
components: {
AppCropper
},
data() {
return {
html: 'https://ebusiness-1255313385.cosbj.myqcloud.com/image/20190823/center2019082304054532.html',
content:''
}
},
methods: {
// 擷取編輯器内容
getContent(content) {
this.content = content
},
// 編輯器内容轉換成線上url
async getcontent2Url() {
try {
const htmlUrl = await this.$refs.tinymce.content2Url()
return htmlUrl
} catch (error) {
console.log(error)
}
}
}
}
</script>
5.使用效果
參考連結
1.https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/Tinymce/index.vue
2.tinymce中文文檔