界面正在加载中,请稍后

Vue整合Ckeditor4-vue(富文本编辑器)

JarryChenJarryChen 发布时间:2020-11-23 文章字数:371 预计用时:1分51秒

# 1. 安装ckeditor4-vue

npm i ckeditor4-vue -s / yarn add ckeditor4-vue

# 2. 在main.js中引入

import Vue from 'vue'
import CKEditor from 'ckeditor4-vue'

Vue.use(CKEditor)

# 3. 自定义组件

  • 默认的组件在使用起来可能还是有点不太方便,同时也为了调整好一些配置和样式,故在ckeditor4的基础上进一步封装组件,旨在方便的进行v-model双向绑定
<template>
    <div id="CkEditor" class="diy-Editor">
        <ckeditor type="classic" v-model="editorData" :config="editorConfig" placeholder="请输入" @ready="initReady" />
    </div>
</template>

<script>
    /* eslint-disable*/
    import CKEditor from 'ckeditor4-vue'
    import $ from 'jquery'
    export default {
        name: 'DiyEditor',
        components: {
            // Use the <ckeditor> component in this view.
            ckeditor: CKEditor.component, // 引入组件
        },
        model: { // 定义双向绑定的槽
            prop: 'content',
            event: 'change',
        },
        props: {
            content: { // 被定义的槽不要给默认值
                type: String,
            },
            uploadUrl: {
                type: String,
                default: '',
            },
        },
        watch: {
            content: { // 如果变量改动直接赋给editorData
                handler() {
                    if (this.content !== this.editorData) this.editorData = this.content
                },
                immediate: true,
            },
            editorData: { // change改变时弹出去赋值
                handler(val) {
                    this.emitData(val)
                },
                deep: true,
            },
        },
        data() {
            return {
                editorData: this.content,
                editor: null, // 获取实例
                debounce: null,
                editorConfig: {
                    enterMode: CKEditor.ENTER_P,
                    extraPlugins: 'divarea,uploadimage', // 这里改成divarea才是使用div进行渲染,同时方便调整样式,否则是使用iframe
                    filebrowserImageUploadUrl: `${process.env.VUE_APP_API_BASE_URL}${this.uploadUrl}`, // 上传图片/截图等调用的post接口
                    filebrowserUploadUrl: `${process.env.VUE_APP_API_BASE_URL}${this.uploadUrl}`,
                    toolbarGroups: [ // 这里是顶部工具条的按钮归类
                        {
                            name: 'document',
                            groups: ['mode', 'document', 'doctools']
                        },
                        {
                            name: 'clipboard',
                            groups: ['clipboard', 'undo']
                        },
                        {
                            name: 'editing',
                            groups: ['find', 'selection', 'spellchecker']
                        },
                        {
                            name: 'forms'
                        },
                        {
                            name: 'basicstyles',
                            groups: ['basicstyles', 'cleanup']
                        },
                        {
                            name: 'paragraph',
                            groups: ['list', 'indent', 'blocks', 'align', 'bidi']
                        },
                        {
                            name: 'links'
                        },
                        {
                            name: 'insert'
                        },
                        {
                            name: 'styles'
                        },
                        {
                            name: 'colors'
                        },
                        {
                            name: 'tools'
                        },
                        {
                            name: 'others'
                        },
                    ],
                },
            }
        },
        methods: {
            initReady(e) { // 这个函数在ckeditor替换掉默认的textarea后执行
                this.editor = e
                $('.cke_editable').removeAttr("title") // 去除title提示
            },
            emitData(val) { // 因为是使用change来监听值改变,需要给一点debounce,这里设置为500ms
                if (this.debounce) {
                    clearTimeout(this.debounce)
                }
                this.debounce = setTimeout(() => {
                    this.$emit('change', val)
                }, 500)
            },
        },
        beforeDestroy() {
            clearTimeout(this.debounce)
            this.debounce = null
        },
    }
</script>

<style lang="less" src='./index.less' />
.diy-Editor {
    .cke {
        border-radius: 6px;
        border       : solid 1px #d9d9d9;
    }

    .cke_inner {
        width : 100%;
        border: none;
    }

    .cke_top {
        background-color: #f9fafa;
        border-color    : #d9d9d9;
    }

    .cke-bottom {
        background-color: #fbfbfb;
        border-color    : #d9d9d9;
    }

    .cke_resizer {
        border-color: transparent rgb(72, 72, 72) transparent transparent;
    }

    a.cke_button_on {
        border-radius: 4px;
        border       : solid 1px #e8eaf1;
    }
}

# 4. 后端响应请求

  • 这一部分主要是针对前端触发上传图片/文件的接口后,进行响应处理,将文件流写成文件然后在response中返回对象,不知是否是ckeditor4中的规定,返回的json对象必须含uploaded, fileName, url字段,其中url字段就是你到时候在富文本编辑器看到的图片/其他内容等。
  • 同时,只要响应成功显示出来,就会将对应的html写到你双向绑定的变量中,直接取值保存即可。

  • 使用 ckeditor4 很大程度在于它相对于其他浏览器可配置更多,功能更多,又相比于 ckeditor5 可以兼容较旧版本浏览器,本文旨在梳理其中的前后端交互及在项目中的一些整合,让后续开发使用到该组件可以无需考虑变量之间的传递问题。

参考

以上部分内容参考自ckeditor4官网