一、简介
TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有:UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。
二、TinyMCE的优势:
- 开源可商用,基于LGPL2.1
- 插件丰富,自带插件基本涵盖日常所需功能(示例看下面的Demo-2)
- 接口丰富,可扩展性强,有能力可以无限拓展功能
- 界面好看,符合现代审美
- 提供经典、内联、沉浸无干扰三种模式(详见“介绍与入门”)
- 对标准支持优秀(自v5开始)
- 多语言支持,官网可下载几十种语言。
三、安装组件
四、官网的引用
<template>
<!-- 全局引入TinyMCE -->
<script src="//unpkg.com/tinymce@5.1.5/tinymce.min.js"></script>
<!-- App -->
<div id="app">
<vue-tinymce v-model="content" :setup="setup" :setting="setting" />
</div>
</template>
<script>
import Vue from "vue"
import VueTinymce from "@packy-tang/vue-tinymce"
//安装组件
Vue.use(VueTinymce)
new Vue({
el: "#app",
data: function() {
return {
content: "<p>html content</p>",
setting: {
height: 500
}
}
},
methods: {
setup(editor) {
console.log(editor)
}
}
})
</script>
五、实际项目
1、在node_modules文件夹 生成的 @packy-tang/vue-tinymce文件夹,将vue-tinymce文件夹 复制到 某个components文件夹里面
2、将tinymce.min.js放于 public/static/js文件夹
下载地址:https://unpkg.com/tinymce@5.1.5/tinymce.min.js
3、问题:
3-1、tinymce.min.js的引用问题
可以直接引用线上的路径,本人建议将tinymce.min.js下载,引用自己项目的路径
- A、代码如下:
<template>
<el-container>
<el-header>
<div><span>校园头条</span><span class="commapp_arrow">></span><span>24小时</span></div>
</el-header>
<el-main class="comm-HeadlinesDiv">
<div class="el-col-md-16 el-col-offset-4">
<div class="card updaterCard">
<div class="myUpdateItem ThemeBorderColor4">
<div class="myUpdateItem_Content">
<div class="msgContainer msg_textarea_Updater">
<div class="mentions-input-box">
<script src="https://unpkg.com/tinymce@5.1.5/tinymce.min.js"></script>
<VueTinymce v-model="h_editHtml" />
</div>
</div>
</div>
</div>
</div>
</div>
</el-main>
</el-container>
</template>
<script>
import { mapActions } from 'vuex'
import VueTinymce from '../components/vue-tinymce/src/vue-tinymce.vue'
export default {
name: 'Hours',
components: {
VueTinymce
},
data() {
return {
h_editHtml: '<h1>11111</h1>'
}
},
methods: {
}
}
</script>
<style>
</style>
- B、报错:
- C、解决:
3-2、vue-tinymce.vue里面的render位置问题
- A、代码如下:
<script>
/**
* 注:编辑器二次刷新处理
* 编辑器二次刷新具体效果为输入光标重置到第一行第一个字前。
* 这种效果根本无法正常录入,其原因是双向绑定数据导致编辑器数据更新所致。
* 根据编辑器的不同状态做标记,当标记为`INPUT`录入时,数据将不会更新至编辑器,
* 从而避免二次更新的情况,具体请看`content`部分和`editor event`部分的代码。
* */
const INIT = 0;
const INPUT = 1;
const CHANGED = 2;
const status = ['INIT', 'INPUT', 'CHANGED']
const changedLog = debug => {
if (!debug) return () => false
console.warn("`@packy-tang/vue-tinymce`进入debug模式");
return (e, _status, val, oldVal) => console.log(`来自:%s | 状态:%s \n %s \n %s`, e.type, status[_status], val, oldVal)
}
export default {
name: "VueTinymce",
model: {
prop: "content",
event: "change"
},
props: {
content: {
type: [String, Object],
default: ''
},
setup: {
type: Function,
default: function() {}
},
disabled: {
type: Boolean,
default: false
},
setting: {
type: Object,
default: function() {
return {};
}
},
debug: Boolean
},
render(createElement) {
if (typeof tinymce === "undefined") {
return createElement('div', "tinymce is undefined");
}
return createElement('div', {
attrs: {
id: this.id
}
});
},
data() {
return {
id: 'vue-tinymce-' + Date.now() + Math.floor(Math.random() * 1000),
editor: null,
status: INIT,
bookmark: null
}
},
watch: {
content(val, oldVal) {
this.changedLog({
type: "propsChanged"
}, this.status, `${val} | ${oldVal}`, "--")
if (this.status === INPUT || oldVal === val) return;
if (!this.editor || !this.editor.initialized)
return; // fix editor plugin is loading and set content will throw error.
if (val === null) return this.resetContent("");
this.setContent(val);
},
disabled(val) {
this.editor.setMode(val ? "readonly" : "design")
}
},
created() {
this.changedLog = changedLog(this.debug)
if (typeof tinymce === "undefined") throw new Error('tinymce undefined');
},
beforeMount() {
const setting = Object.assign({},
this.setting, {
selector: '#' + this.id,
setup: (editor) => {
this.setup(editor);
// console.log('setup');
editor.on('init', () => {
// console.log('init', this.content);
this.setContent(this.content, editor)
editor.on('keyup input', e => { //只在编辑器中打字才会触发
this.status = INPUT //编辑器录入文字时标记为`INPUT`状态
})
editor.on('SetContent', e => { //编辑器在插入图片和撤销/重做时触发,组件content更新数据也会导致触发
this.changedLog(e, this.status, editor.getContent(), "--")
})
editor.on('Blur', e => {
this.status = INIT
this.changedLog(e, this.status, editor.getContent(), "--")
})
editor.on('input keyup Change Undo Redo ExecCommand NodeChange', e => {
this.onChanged(e, editor)
})
});
}
}
);
this.editor = tinymce.createEditor(setting.selector, setting)
},
mounted() {
this.editor.targetElm = this.$el
this.editor.render()
},
updated() {
this.editor.render()
},
beforeDestroy: function() {
this.editor.remove();
},
methods: {
setContent(val, editor) {
if (!editor) editor = this.editor
editor.setContent(val)
editor.selection.moveToBookmark(this.bookmark)
},
resetContent(val, editor) {
if (!editor) editor = this.editor
if (!!editor.resetContent) return editor.resetContent(val)
editor.setContent(val)
editor.setDirty(false)
editor.undoManager.clear()
},
onChanged(e, editor) {
if (!editor) editor = this.editor
if (e.type === 'change') this.bookmark = e.level.bookmark
const content = editor.getContent()
this.changedLog(e, this.status, content, "--")
this.$emit('change', content);
}
}
}
</script>
- B、报错:
-
C、解决:
3-3、CHANGELOG.md
- A、报错:
- B、解决:
3-4、README.md
- A、报错:
- B、解决:
3-5、LICENSE
- A、报错:
- B、解决:
3-6、vue-tinymce.cjs.js.map缺少module.exports =
- A、代码如下:
- B、报错:
- C、解决:
3-7、vue-tinymce.esm.js.map缺少module.exports =
- A、代码如下:
- B、报错:
- C、解决:
3-8、vue-tinymce.umd.js.map缺少module.exports =
- A、代码如下:
- B、报错:
- C、解决:
3-9、Uncaught SyntaxError: Unexpected token '<'
- A、代码如下:
- B、报错:
- C、解决: