最近在vue我的项目里应用到了tinymce富文本编辑器,途中遇到不少bug,然而网上又没有很好的解决,最初摸索进去,记录一下。
下载tinymce
这里并不需要用npm装置tinymce,也不装置tinymce-vue。网上有教程说npm i tinymce装置后,把node_modules里的文件拷贝进去到public文件里,而后在index.html里援用的。都不须要!间接上官网下载你须要的版本的tinymce包并解压,以及下载对应版本的中文语言包,将zh_CN.js文件放到tinymce的langs文件夹外面。
新建组件
在我的项目的components里,新建一个组件,例如取名TinyEditor,并新建index.vue组件文件。将tinymce里的所有文件,拷贝到这个组件里。构造如下
组件文件
<template>
<div id="tinyeditor"></div>
</template>
引入必须的文件tinymce.min.js、theme.min.js,以及须要的插件、语言包。
import './tinymce.min.js';
import './plugins/lists/plugin.min.js';
import './plugins/code/plugin.min.js';
import './plugins/textpattern/plugin.min.js';
import './themes/silver/theme.min.js';
import './langs/zh_CN';
在款式局部引入款式文件
@import url('./skins/ui/oxide/skin.min.css');
增加插件
例如首行缩进、行高设置等官网没有提供的插件,下载下来后,间接放到TinyEditor下的plugins文件夹里,而后在组件文件里引入,留神引入程序要tinymce.min.js之后。
import './tinymce.min.js';
import './plugins/lists/plugin.min.js';
import './plugins/code/plugin.min.js';
import './plugins/textpattern/plugin.min.js';
import './plugins/indent2em/plugin.min.js';
import './plugins/lineheight/plugin.min.js';
import './themes/silver/theme.min.js';
import './langs/zh_CN';
残缺代码
这里并没有应用数据绑定,因而须要在初始化时将内容增加进去,并监听批改的事件。特地留神要在destroyed的时候清理对象,因为tinymce是一个全局对象。
<template>
<div id="tinyeditor"></div>
</template>
<script>
// 去掉html标签,预防xss攻打
function removeTags(str, tagsToKeep) {
const tagsRegExp = new RegExp(`<(?!\/?(${tagsToKeep.join('|')})\s*\/?>)[^>]+>`, 'gi');
return str.replace(tagsRegExp, '');
}
import './tinymce.min.js';
import './plugins/lists/plugin.min.js';
import './plugins/code/plugin.min.js';
import './plugins/textpattern/plugin.min.js';
import './plugins/indent2em/plugin.min.js';
import './plugins/lineheight/plugin.min.js';
import './themes/silver/theme.min.js';
import './langs/zh_CN';
export default {
name: 'editor',
data() {
return {
editor: null,
init: {
selector: '#tinyeditor',
height: 600,
language: 'zh_CN',
plugins: 'lists code indent2em textpattern lineheight', //插件
toolbar: [
'undo redo code | bold italic underline strikethrough | fontsizeselect | formatselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | indent2em lineheight',
'indent outdent | bullist numlist | blockquote | removeformat',
], //工具栏
branding: false, //去除版权信息
menubar: false, //去除菜单栏
paste_preprocess: (pl, o) => {
o.content = removeTags(o.content, 'sup,sub');
},
init_instance_callback: (editor) => {
this.editor = editor;
if (this.value) {
editor.setContent(this.value); // 设置内容
}
// 监听内容变动的形式
editor.on('NodeChange Change KeyUp SetContent', () => {
this.$emit('input', editor.getContent());
});
}, // 初始化回调函数
},
};
},
props: {
value: {
type: String,
default: '',
},
},
mounted() {
tinymce.init(this.init);
},
destroyed() {
tinymce.remove(this.editor);
},
};
</script>
<style scoped lang="scss">
@import url('./skins/ui/oxide/skin.min.css');
</style>
引入组件
我这里增加一个v-if,因为我要在弹窗里应用,所以要确保每次敞开弹窗时要毁掉组件。
<tiny-editor v-if="open" v-model="content" @input="res => content = res"></tiny-editor>
发表回复