-
Instale dos complementos tinymce y @tinymce/tinymce-vue
npm instalar [email protected] @tinymce/[email protected] -S
Aviso:
- @tinymce/tinymce-vue es un paquete vue para tinymce, utilizado principalmente como componente vue
- -S Guardar en el archivo package.json
2. Copie los directorios ( iconos , complementos , máscaras , temas ) en node_modules/tinymce a public/tinymce
3. Sinice el idioma en tinymce, descargue langs/zh_CN.js, [dirección de descarga del paquete de idioma](https://www.tiny.cloud/get-tiny/language-packages/)
elegir
4. Descomprima y copie el archivo langs a public/tinymce
5. Introduce el editor tinymce
importar TinymceRich desde "@tinymce/tinymce-vue";
6. Introduzca los archivos relacionados con tinymce en node_modules
importar tinymce desde "tinymce/tinymce";
7. Usa el componente TinymceRich
8. Introducción a los complementos del editor
import 'tinymce/themes/silver'
import 'tinymce/plugins/advlist' //高级列表
import 'tinymce/plugins/anchor' //锚点
import 'tinymce/plugins/autolink' //自动链接
import 'tinymce/plugins/autosave'//编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效
import 'tinymce/plugins/code'//编辑源码
import 'tinymce/plugins/codesample'//代码示例
import 'tinymce/plugins/directionality'//文字方向
import 'tinymce/plugins/fullscreen'全屏插件
import 'tinymce/plugins/hr'//水平分割线
import 'tinymce/plugins/insertdatetime'//插入日期时间
import 'tinymce/plugins/link'//链接插件
import 'tinymce/plugins/lists'列表插件
import 'tinymce/plugins/media' //媒体插件
import 'tinymce/plugins/nonbreaking'//插入不间断空格
import 'tinymce/plugins/noneditable'
import 'tinymce/plugins/pagebreak'//插入分页符
import 'tinymce/plugins/paste' //预览
import 'tinymce/plugins/print'//打印
import 'tinymce/plugins/save' //保存
import 'tinymce/plugins/searchreplace'//查找替换
// import 'tinymce/plugins/spellchecker' //拼写检查,未加入汉化,不建议使用
import 'tinymce/plugins/tabfocus'//切入切出,按tab键切出编辑器,切入页面其他输入框中
import 'tinymce/plugins/template'//内容模板
import 'tinymce/plugins/textpattern'//快速排版
import 'tinymce/plugins/visualblocks' //显示元素范围
import 'tinymce/plugins/visualchars' //显示不可见字符
import 'tinymce/plugins/wordcount'//字数统计
import 'tinymce/plugins/table'//表格插件
import "tinymce/plugins/textcolor"; //文字颜色
import "tinymce/plugins/toc"; //目录生成器
9. Personalice los atributos para los componentes de RichText (estado deshabilitado deshabilitado, complementos disponibles, barra de herramientas de la barra de herramientas, modelValue se usa para personalizar la directiva v-model de los componentes de RichText, el nombre es fijo)
<div>
<TinymceRich v-model="contentValue" :init="initOption" :disabled="disabled" />
</div>
10. Inicialice el componente Editor, defínalo en la opción data() y realice la carga de la imagen
let initOption = ref({
base_url: '/tinymce', // [必要参数] 指定public的目录
language_url: "/tinymce/langs/zh-Hans.js",//语言类型的路径
language: 'zh-Hans', // 语言类型(中文),默认会到tinymce/langs/zh_CN.js文件
skin_url: '/tinymce/skins/ui/oxide', // 皮肤,浅色
// skin_url: '/tinymce/skins/ui/oxide-dark', // 皮肤,深色
plugins: props.plugins, // 插件配置
toolbar: props.toolbar, // 工具栏配置,设置false则为隐藏
toolbar_mode: 'sliding', // 工具栏移除模式,floating / sliding / scrolling / wrap
// menubar: 'file edit', // 菜单栏配置,设置为false则隐藏,不配置默认显示全部菜单
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', // 字体大小
font_formats: '微软雅黑=Microsoft YaHei, Helvetica Neue, PingFang SC, sans-serif; 苹果苹方=PingFang SC, Microsoft YaHei, sans-serif; 宋体=simsun,serif; 仿宋体=FangSong,serif; Impact=impact,chicago', // 字体
lineheight_formats: '0.5 0.8 1 1.2 1.5 1.75 2.2.5 3 4 5', // 行高配置,也可配置成'12px 14px 16px 18px'这种形式
height: 400, // 注:引入autoresize插件时,此属性无效
placeholder: '在这里输入文字',
branding: false, // tiny技术支持信息是否显示
resize: false, // 编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可(注意引号)
// statusbar: false, // 最下方的元素路径和字数统计那一栏是否显示
elementpath: false, // 元素路径是否显示
content_style: 'img { max-width: 100%; }', // 自定义可编辑区的css样式
setup: function (editor: any) {
editor.ui.registry.addIcon(
"image",
`<svg t="1664002320321" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4420" width="24" height="24"><path d="M125.9 185h772.2v653.9H125.9z" fill="#1F53CC" p-id="4421"></path><path d="M164.7 217.2h694.6v516.7H164.7z" fill="#FECD44" p-id="4422"></path><path d="M458.9 734l-8.6-43.8-101.5-102.8-135 146.6z" fill="#FC355D" p-id="4423"></path><path d="M306.9 348.7m-66.7 0a66.7 66.7 0 1 0 133.4 0 66.7 66.7 0 1 0-133.4 0Z" fill="#FFFFFF" p-id="4424"></path><path d="M384.6 734h474.7V608.8L687.8 400.1z" fill="#FC355D" p-id="4425"></path><path d="M422.5 662l-37.9 72 52.1-57.5z" fill="#BF2847" p-id="4426"></path><path d="M302.5 778.9h418.9v16.7H302.5z" fill="#00F0D4" p-id="4427"></path></svg>`
);
editor.ui.registry.addIcon('preview', '<svg t="1664002320321" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4420" width="24" height="24"><path d="M125.9 185h772.2v653.9H125.9z" fill="#1F53CC" p-id="4421"></path><path d="M164.7 217.2h694.6v516.7H164.7z" fill="#FECD44" p-id="4422"></path><path d="M458.9 734l-8.6-43.8-101.5-102.8-135 146.6z" fill="#FC355D" p-id="4423"></path><path d="M306.9 348.7m-66.7 0a66.7 66.7 0 1 0 133.4 0 66.7 66.7 0 1 0-133.4 0Z" fill="#FFFFFF" p-id="4424"></path><path d="M384.6 734h474.7V608.8L687.8 400.1z" fill="#FC355D" p-id="4425"></path><path d="M422.5 662l-37.9 72 52.1-57.5z" fill="#BF2847" p-id="4426"></path><path d="M302.5 778.9h418.9v16.7H302.5z" fill="#00F0D4" p-id="4427"></path></svg>');
},
paste_data_images: true, // 图片是否可以粘贴
images_upload_handler: (blobInfo: any, success: any, failure: any) => {//自定义图片上传
// let img = 'data:image/jpeg;base64,' + blobInfo.base64();
let formData = new FormData();//创建一个表单对象
formData.append('file', blobInfo.blob());//通过formData对象封装图片二进制数据
upload(formData).then((res: any) => {//上传的图片路径
success(res.data.url);//返回图片的回调地址
}).catch((err: any) => {
failure(err.response.data.message);
})
}
});
11. Personalice el modo v del componente RichText, defina el atributo calculado contentValue y use get y set para completar hábilmente el enlace de datos entre los componentes RichText y Editor
let props = defineProps({//自定义属性用于设置默认值
modelValue: {// 用于自定义v-model的value 父组件向子组件传递的值
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
plugins: { //插件
type: [String, Array],
default: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap nonbreaking anchor insertdatetime advlist lists wordcount autosave'
},
toolbar: { //工具栏
type: [String, Array],
default: 'fullscreen undo redo restoredraft | table image media charmap hrpagebreak insertdatetime print preview | cut copy paste pastetext | forcolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | code selectal searchreplace visualblocks indent2em lineheight formatpainter axupimgs'
}
});
// 计算属性
let contentValue = computed({
// 富文本框内容
get() { // 取值 父组件向子组件传值
return props.modelValue;
},
set(value: string) { // 赋值 子组件向父组件传值 ,吧value传递过去,
emit('update:modelValue', value)
}
})
código general
<template>
<div>
<TinymceRich v-model="contentValue" :init="initOption" :disabled="disabled" />
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import tinymce from "tinymce/tinymce";
import TinymceRich from "@tinymce/tinymce-vue";
import { upload } from "@/utils/http";
// 引入编辑器插件
import 'tinymce/themes/silver'
import 'tinymce/plugins/advlist' //高级列表
import 'tinymce/plugins/anchor' //锚点
import 'tinymce/plugins/autolink' //自动链接
import 'tinymce/plugins/autosave'//编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效
import 'tinymce/plugins/code'//编辑源码
import 'tinymce/plugins/codesample'//代码示例
import 'tinymce/plugins/directionality'//文字方向
import 'tinymce/plugins/fullscreen'全屏插件
import 'tinymce/plugins/hr'//水平分割线
import 'tinymce/plugins/insertdatetime'//插入日期时间
import 'tinymce/plugins/link'//链接插件
import 'tinymce/plugins/lists'列表插件
import 'tinymce/plugins/media' //媒体插件
import 'tinymce/plugins/nonbreaking'//插入不间断空格
import 'tinymce/plugins/noneditable'
import 'tinymce/plugins/pagebreak'//插入分页符
import 'tinymce/plugins/paste' //预览
import 'tinymce/plugins/print'//打印
import 'tinymce/plugins/save' //保存
import 'tinymce/plugins/searchreplace'//查找替换
// import 'tinymce/plugins/spellchecker' //拼写检查,未加入汉化,不建议使用
import 'tinymce/plugins/tabfocus'//切入切出,按tab键切出编辑器,切入页面其他输入框中
import 'tinymce/plugins/template'//内容模板
import 'tinymce/plugins/textpattern'//快速排版
import 'tinymce/plugins/visualblocks' //显示元素范围
import 'tinymce/plugins/visualchars' //显示不可见字符
import 'tinymce/plugins/wordcount'//字数统计
import 'tinymce/plugins/table'//表格插件
import "tinymce/plugins/textcolor"; //文字颜色
import "tinymce/plugins/toc"; //目录生成器
let props = defineProps({//自定义属性用于设置默认值
modelValue: {// 用于自定义v-model的value 父组件向子组件传递的值
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
plugins: { //插件
type: [String, Array],
default: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap nonbreaking anchor insertdatetime advlist lists wordcount autosave'
},
toolbar: { //工具栏
type: [String, Array],
default: 'fullscreen undo redo restoredraft | table image media charmap hrpagebreak insertdatetime print preview | cut copy paste pastetext | forcolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | code selectal searchreplace visualblocks indent2em lineheight formatpainter axupimgs'
}
});
let emit = defineEmits(['update:modelValue']);
let initOption = ref({
base_url: '/tinymce', // [必要参数] 指定public的目录
language_url: "/tinymce/langs/zh-Hans.js",//语言类型的路径
language: 'zh-Hans', // 语言类型(中文),默认会到tinymce/langs/zh_CN.js文件
skin_url: '/tinymce/skins/ui/oxide', // 皮肤,浅色
// skin_url: '/tinymce/skins/ui/oxide-dark', // 皮肤,深色
plugins: props.plugins, // 插件配置
toolbar: props.toolbar, // 工具栏配置,设置false则为隐藏
toolbar_mode: 'sliding', // 工具栏移除模式,floating / sliding / scrolling / wrap
// menubar: 'file edit', // 菜单栏配置,设置为false则隐藏,不配置默认显示全部菜单
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', // 字体大小
font_formats: '微软雅黑=Microsoft YaHei, Helvetica Neue, PingFang SC, sans-serif; 苹果苹方=PingFang SC, Microsoft YaHei, sans-serif; 宋体=simsun,serif; 仿宋体=FangSong,serif; Impact=impact,chicago', // 字体
lineheight_formats: '0.5 0.8 1 1.2 1.5 1.75 2.2.5 3 4 5', // 行高配置,也可配置成'12px 14px 16px 18px'这种形式
height: 400, // 注:引入autoresize插件时,此属性无效
placeholder: '在这里输入文字',
branding: false, // tiny技术支持信息是否显示
resize: false, // 编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可(注意引号)
// statusbar: false, // 最下方的元素路径和字数统计那一栏是否显示
elementpath: false, // 元素路径是否显示
content_style: 'img { max-width: 100%; }', // 自定义可编辑区的css样式
setup: function (editor: any) {
editor.ui.registry.addIcon(
"image",
`<svg t="1664002320321" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4420" width="24" height="24"><path d="M125.9 185h772.2v653.9H125.9z" fill="#1F53CC" p-id="4421"></path><path d="M164.7 217.2h694.6v516.7H164.7z" fill="#FECD44" p-id="4422"></path><path d="M458.9 734l-8.6-43.8-101.5-102.8-135 146.6z" fill="#FC355D" p-id="4423"></path><path d="M306.9 348.7m-66.7 0a66.7 66.7 0 1 0 133.4 0 66.7 66.7 0 1 0-133.4 0Z" fill="#FFFFFF" p-id="4424"></path><path d="M384.6 734h474.7V608.8L687.8 400.1z" fill="#FC355D" p-id="4425"></path><path d="M422.5 662l-37.9 72 52.1-57.5z" fill="#BF2847" p-id="4426"></path><path d="M302.5 778.9h418.9v16.7H302.5z" fill="#00F0D4" p-id="4427"></path></svg>`
);
editor.ui.registry.addIcon('preview', '<svg t="1664002320321" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4420" width="24" height="24"><path d="M125.9 185h772.2v653.9H125.9z" fill="#1F53CC" p-id="4421"></path><path d="M164.7 217.2h694.6v516.7H164.7z" fill="#FECD44" p-id="4422"></path><path d="M458.9 734l-8.6-43.8-101.5-102.8-135 146.6z" fill="#FC355D" p-id="4423"></path><path d="M306.9 348.7m-66.7 0a66.7 66.7 0 1 0 133.4 0 66.7 66.7 0 1 0-133.4 0Z" fill="#FFFFFF" p-id="4424"></path><path d="M384.6 734h474.7V608.8L687.8 400.1z" fill="#FC355D" p-id="4425"></path><path d="M422.5 662l-37.9 72 52.1-57.5z" fill="#BF2847" p-id="4426"></path><path d="M302.5 778.9h418.9v16.7H302.5z" fill="#00F0D4" p-id="4427"></path></svg>');
},
paste_data_images: true, // 图片是否可以粘贴
images_upload_handler: (blobInfo: any, success: any, failure: any) => {//自定义图片上传
// let img = 'data:image/jpeg;base64,' + blobInfo.base64();
let formData = new FormData();//创建一个表单对象
formData.append('file', blobInfo.blob());//通过formData对象封装图片二进制数据
upload(formData).then((res: any) => {//上传的图片路径
success(res.data.url);//返回图片的回调地址
}).catch((err: any) => {
failure(err.response.data.message);
})
}
});
// 计算属性
let contentValue = computed({
// 富文本框内容
get() { // 取值 父组件向子组件传值
return props.modelValue;
},
set(value: string) { // 赋值 子组件向父组件传值 ,吧value传递过去,
emit('update:modelValue', value)
}
})
</script>
Representaciones: