wangEditor 是一款比较流行的富文本编辑器,它比较轻量级,并且很容易通过css来定制化样式
下面的代码是用ts写的,如果是js的话,转换一下就行了,只是语法不一样
<template> <div class="editor"> <div ref="toolbar" class="editor_toolbar" :class="toolbarClass" ></div> <div ref="editor" class="editor_text" :class="textClass" ></div> </div> </template> <script lang="ts"> import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator' import WangEditor from 'wangeditor' @Component({ components: { } }) export default class Editor extends Vue { @Model('update', { type: String, default: '' }) public content!: string @Prop({ default: false }) public isClear?: boolean @Prop({ default: () => { return [ 'bold', // 粗体 'italic', // 斜体 'head', // 标题 'quote', // 引用 // 'code', // 插入代码 'list', // 列表 // 'fontSize', // 字号 // 'fontName', // 字体 'underline', // 下划线 'strikeThrough', // 删除线 // 'foreColor', // 文字颜色 // 'backColor', // 背景颜色 'link', // 插入链接 // 'justify', // 对齐方式 // 'emoticon', // 表情 'image', // 插入图片 'table', // 表格 'video', // 插入视频 'undo', // 撤销 'redo', // 重复 'fullscreen' // 全屏 ] } }) public menus?: [] @Prop({ default: '' }) public toolbarClass?: boolean @Prop({ default: '' }) public textClass?: boolean public editor: any = null public info: any = null public flag: boolean = false @Watch('isClear') public isClearChange(val: boolean) { const me: any = this if (val) { me.editor.txt.clear() me.info = null } } @Watch('content', {deep: true, immediate: true}) public contentChange(val: string) { const me: any = this me.$nextTick(() => { if (val !== me.editor.txt.html() && !me.flag) { me.editor.txt.html(val.replace(/\#image/g, 'data:image')) } me.flag = false }) } public seteditor() { const me: any = this me.editor = new WangEditor(me.$refs.toolbar, me.$refs.editor) // me.editor.customConfig.pasteFilterStyle = false me.editor.customConfig.uploadImgShowBase64 = true // base 64 存储图片 // me.editor.customConfig.uploadImgServer = 'http://otp.cdinfotech.top/file/upload_images'// 配置服务器端地址 // me.editor.customConfig.uploadImgHeaders = { }// 自定义 header me.editor.customConfig.uploadFileName = 'file' // 后端接受上传文件的参数名 me.editor.customConfig.uploadImgMaxSize = 2 * 1024 * 1024 // 将图片大小限制为 2M me.editor.customConfig.uploadImgMaxLength = 6 // 限制一次最多上传 3 张图片 me.editor.customConfig.uploadImgTimeout = 3 * 60 * 1000 // 设置超时时间 me.editor.customConfig.menus = me.menus me.editor.customConfig.uploadImgHooks = { faile: me.uploadImgFail, success: me.uploadImgSuccess, timeout: me.uploadImgTimeout, error: me.uploadImgError, customInsert: me.uploadImgCustomInsert, } me.editor.customConfig.onchange = me.initContent me.editor.customConfig.pasteTextHandle = me.pasteTextHandler // 创建富文本编辑器 me.editor.create() } public pasteTextHandler(content: string) { // content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回 if (content === '' && !content) { return '' } let str = content str = str.replace(/<xml>[\s\S]*?<\/xml>/ig, '') str = str.replace(/<style>[\s\S]*?<\/style>/ig, '') str = str.replace(/<\/?[^>]*>/g, '') str = str.replace(/[ | ]*\n/g, '\n') str = str.replace(/ /ig, '') // console.log('****', content) // console.log('****', str) return str } public uploadImgFail(xhr: any, editor: any, res: any) { const me: any = this } public uploadImgSuccess(xhr: any, editor: any, res: any) { const me: any = this } public uploadImgTimeout(xhr: any, editor: any) { const me: any = this } public uploadImgError(xhr: any, editor: any) { const me: any = this } public uploadImgCustomInsert(insertImg: any, result: any, editor: any) { const me: any = this const url = 'http://otp.cdinfotech.top' + result.url insertImg(url) } public initContent(html: string) { const me: any = this me.info = html // 绑定当前值 me.flag = true // me.editor.txt.html(html) me.$emit('update', me.info) // 将内容同步到父组件中 } public mounted() { const me: any = this me.seteditor() me.editor.txt.html(this.content.replace(/\#image/g, 'data:image')) } } </script> <style lang="scss" scoped> .editor { position: relative; z-index: 0; width: 100%; margin: 0 auto; } .editor_toolbar { border: 1px solid #CCC; } .editor_text { min-height: 120px; border: 1px solid #CCC; border-top: none; } </style>
在组件中使用
<template> <div> <editor v-model="content" @change="contentChange" ></editor> </div> </template> <script> import { Vue, Component } from 'vue-property-decorator' export default Vue.extend({ data() { return { content: '', } }, methods: { contentChange() {} } }) </script>