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>