针对项目需求,苦苦研究tinymce英文api一周时间,终于搞清楚了如何开发,不定期分享一下开发经验。首先我们讲如何在vue中方便的开发插件。
tinymce 此页英文文档:https://www.tiny.cloud/docs/configure/editor-appearance/
先看一下效果:
模板库维护页面:
编辑器模板库呈现效果:
1、项目说明
本项目基于vue开发,tinymce没有针对vue专属的插件开发方法,只能用原生js编辑插件然后导入插件,但是我不想放弃element-ui这么强大的vue组件库,耗费精力去写样式,所以我简化操作,直接在引入tinymce时使用setup方法,在方法内注入按钮和对应的操作,代码如下:
//注入模板库
setup: (editor) => { //注入模板库 editor.ui.registry.getAll().icons.templatestore || editor.ui.registry.addIcon('templatestore', `<svg t="1589192112197" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4265" width="20" height="20"> <path d="M85.344 0v1024h853.344V0H85.344z m768 938.656H170.688V85.312h682.656v853.344z" p-id="4266"></path><path d="M256 170.656h512v170.656H256V170.656zM426.656 426.656H768V512H426.656v-85.344zM426.656 597.344H768v85.344H426.656v-85.344zM426.656 768H768v85.344H426.656V768zM256 426.656h85.344v426.656H256V426.656z" p-id="4267"></path></svg>` );
editor.ui.registry.addButton('templatestore', { icon: 'templatestore', tooltip: '模板库', onAction: () => { this.$refs.store.open(); } }); },
//引入模板库组件
<template> <div class="tinymce-box"> <!-- <button @click="inset">插入</button> --> <editor v-model="myValue" :init="init" :disabled="disabled" @onClick="onClick"> </editor> //模板库
<template-store ref="store" @interpositionFun="insertTemplate"></template-store>
</div>对如何引用vue组件我就不在这里详细描述了,组件内的代码给大家呈现一下,都是基于element组件库的
<template> <el-dialog title="模板库" :visible.sync="dialogVisible" width="820px"> <div class="template-store"> <el-form :inline="true" :model="form" class="demo-form-inline"> <el-form-item label="模板名称"> <el-input v-model="form.templateName" placeholder="模板名称"></el-input> </el-form-item> <el-form-item label="是否公开"> <el-select v-model="form.isPublic" placeholder="是否公开"> <el-option label="是" value="1"></el-option> <el-option label="否" value="0"></el-option> </el-select> </el-form-item> <el-form-item> <el-button type="primary" @click="fetchList" size="mini">查询</el-button> </el-form-item> <el-button type="primary" @click="onSubmit(true)" size="mini" style="float:right;margin-top:4px">插入</el-button> <el-button type="primary" @click="onSubmit(false)" size="mini" style="float:right;margin:4px 4px 0 0">替换</el-button> </el-form> <div class="dialog_content_list"> <span v-for="(item, index) in tableData" :key="index"> <div :class="item.isAction ? 'dialog_list_item select_list_item' : 'dialog_list_item'" @click="selectTemplate(item, index)"> <el-image :src="item.coverUrls || defautUrl"></el-image> <div class="dialog_list_item_tit" :title="item.templateName || '暂无'">{{ item.templateName || '暂无' }}</div> <time>{{ item.createTime }}</time> <span class="sanjiao"></span> </div> </span> </div> <div class="pagination_box"> <el-pagination :current-page.sync="page.current" :page-size="page.size" @current-change="paginationCurrentChange" @size-change="paginationSizeChange" layout="total, sizes ,prev, pager, next, jumper" :total="page.total"> </el-pagination> </div> </div> </el-dialog></template>
<script> import { getTemplate } from '@/api/yc/template'
export default { name:'templateStore', data() { return { dialogVisible:false, value:'',
page: { total: 0, // 总页数 currentPage: 1, // 当前页数 pageSize: 8 // 每页显示多少条 },
tableData:[], tableIndex:'',
form:{ templateName:'', isPublic:'', content:'', }, defautUrl: require('@/assets/images/default_audio.jpg'), } }, created(){ this.fetchList(); }, methods: { open(){ this.dialogVisible = true }, fetchList(){ getTemplate(Object.assign({ current: this.page.currentPage, size: this.page.pageSize }, this.form)).then(({data:res}) => { this.tableData = res.data.records.map(item=>{ item.isAction = false; return item; }); this.page.total = res.data.total }) }, //确定选择 onSubmit(status){ if(!this.tableIndex){ this.$message.error('请选择模板') return false }
this.$emit('interpositionFun',{ data:this.tableData[this.tableIndex].content, status:status, }); this.dialogVisible = false; }, selectTemplate (item, index) {
if(this.tableIndex === index){ this.tableData[index].isAction = false; this.tableIndex = ''; return }
if(this.tableIndex || this.tableIndex === 0){ this.tableData[this.tableIndex].isAction = false; }
this.tableIndex = index; this.tableData[index].isAction = true; }, // 分页 paginationSizeChange (val) { this.page.size = val this.fetchList() }, paginationCurrentChange (val) { this.page.current = val this.fetchList() }, } }</script>
<style lang="scss">$color: #e5e5e5;.template-store{ .dialog_content_list { margin-top: 10px; .dialog_list_item { display: inline-block; margin-right: 14px; margin-bottom: 20px; padding: 10px; border: 1px solid $color; position: relative; overflow: hidden; cursor: pointer; max-width: 180px; .el-image { width: 160px; height: 120px; } .dialog_list_item_tit { font-size: 14px; color: #333; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 26px; } time { color: #9a9a9a; font-size: 12px; } .sanjiao { display: inline-block; width: 50px; height: 20px; background: $color; position: absolute; top: -6px; right: -14px; transform: rotate(45deg); &::before { display: inline-block; content: '✓'; color: #fff; position: absolute; top: 1px; right: 15px; transform: rotate(-45deg); } } } .select_list_item { border-color: #268bff; .sanjiao { background: #268bff; } } } .pagination_box { text-align: right; padding-bottom: 20px; }}</style>如果想更好的封装其实也是可以的,但是我想用的插件可能就只有模板库、图片库,所以暂时就这样吧。
下篇我们讲一下如何使用tinymce快捷键