vue中使用ckeditor

很多项目中都需要使用富文本编辑器,市面上关于富文本编辑器的js库也有很多。个人使用过wangEditor,TinyMce以及ckeditor。各有各的优缺点,就不一一论述。此文单独讲述ckeditor的使用方式,包括ckeditor4以及ckeditor5搭配vue的使用方法以及如何自定义一些功能。

ckeditor5

ckeditor5提供了所见即所得的各种编辑解决方案。从类似于googledocs和Medium的编辑器,到Slack或类似Twitter的应用程序,所有这些都可以在一个编辑框架内实现。

ckeditor有多种模式可以选择:Classic, Balloon,Ballon Block, Inline,Document, Pagination,可以根据自己需求下载安装各自模式。详情文档自行参考官方文档

  1. 在线demo

  2. ckeditor5文档

因为Document本身自带可以编辑的东西更多,此处以Document为例:

下载安装

下载安装页面

npm install --save @ckeditor/ckeditor5-build-decoupled-document
自定义图片上传

我们需要自定义一个图片上传的适配器,参照官方文档,完整的上传图片适配器代码如下:

uploadAdapter.js

import axios from 'axios'
export default class UploadAdapter {
  constructor(loader) {
    this.loader = loader
  }
  upload() {
    return this.loader.file.then(file => new Promise((resolve, reject) => {
      const data = new FormData()
      data.append('file', file)
      axios.request({
        url: `/services/businessservice/api/attachments/uploadFile`,// 上传文件的接口地址,实际请填写完整地址
        method: 'post',
        data,
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(res => {
        console.log(res)
        if (res.data.meta.code === 200) {
          const url = res.data.url // 后台返回的上传成功后的图片地址
          resolve({
            default: url
          })
        }
      }).catch(error => {
        reject(error)
      })
    }))
  }
  abort() {
  }
}


完整功能代码实现

为了让富文本编辑器看上去更像word,可以自定义设置一些样式,可以根据自己需求增加或者删除一些toolbar工具栏以及设置自己需要的语言,完整代码如下,图片上传需要引入上面自定义的图片上传的适配器

<template>
  <div class="rich-container">
    <div class="rich-editor document-editor">
      <div id="toolbar-container" class="document-editor__toolbar" />
      <div class="document-editor__editable-container">
        <div id="editor" class="document-editor__editable" />
      </div>
    </div>
  </div>
</template>
<script>

import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document'
import '@ckeditor/ckeditor5-build-decoupled-document/build/translations/zh-cn' // 中文包
import UploadAdapter from './uploadAdapter.js'
export default {
  data() {
    return {
      editor: null // 编辑器实例
    }
  },
  mounted() {
    this.initCKEditor()
  },
  methods: {
    initCKEditor() {
      // 初始化编辑器
      DecoupledEditor.create(document.querySelector('#editor'), {
        language: 'zh-cn', // 中文
        removePlugins: ['MediaEmbed'] // 除去视频按钮
      }).then(editor => {
        editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
          return new UploadAdapter(loader)
        }
        const toolbarContainer = document.querySelector('#toolbar-container')
        toolbarContainer.appendChild(editor.ui.view.toolbar.element)
        this.editor = editor // 将编辑器保存起来,用来随时获取编辑器中的内容等,执行一些操作
      }).catch(error => {
        console.error(error)
      })
    }
  }
}
</script>
<style lang="scss">
.rich-editor {
  width: 60%;
  min-height: 500px;
  margin: 20px auto;
}
</style>
<style lang="css">
.document-editor {
		border: 1px solid var(--ck-color-base-border);
		border-radius: var(--ck-border-radius);

		/* Set vertical boundaries for the document editor. */
		max-height: 700px;

		/* This element is a flex container for easier rendering. */
		display: flex;
		flex-flow: column nowrap;
	}

	.document-editor__toolbar {
		/* Make sure the toolbar container is always above the editable. */
		z-index: 1;

		/* Create the illusion of the toolbar floating over the editable. */
		box-shadow: 0 0 5px hsla( 0,0%,0%,.2 );

		/* Use the CKEditor CSS variables to keep the UI consistent. */
		border-bottom: 1px solid var(--ck-color-toolbar-border);
	}

	/* Adjust the look of the toolbar inside of the container. */
	.document-editor__toolbar .ck-toolbar {
		border: 0;
		border-radius: 0;
	}

	/* Make the editable container look like the inside of a native word processor app. */
	.document-editor__editable-container {
		padding: calc( 2 * var(--ck-spacing-large) );
		background: var(--ck-color-base-foreground);

		/* Make it possible to scroll the "page" of the edited content. */
		overflow-y: scroll;
	}

	.document-editor__editable-container .document-editor__editable.ck-editor__editable {
		/* Set the dimensions of the "page". */
		width: 15.8cm;
		min-height: 21cm;

		/* Keep the "page" off the boundaries of the container. */
		padding: 1cm 2cm 2cm;

		border: 1px hsl( 0,0%,82.7% ) solid;
		border-radius: var(--ck-border-radius);
		background: white;

		/* The "page" should cast a slight shadow (3D illusion). */
		box-shadow: 0 0 5px hsla( 0,0%,0%,.1 );

		/* Center the "page". */
		margin: 0 auto;
	}

	/* Override the page's width in the "Examples" section which is wider. */
	.main__content-wide .document-editor__editable-container .document-editor__editable.ck-editor__editable {
		width: 18cm;
	}

	/* Set the default font for the "page" of the content. */
	.document-editor .ck-content,
	.document-editor .ck-heading-dropdown .ck-list .ck-button__label {
		font: 16px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
	}

	/* Adjust the headings dropdown to host some larger heading styles. */
	.document-editor .ck-heading-dropdown .ck-list .ck-button__label {
		line-height: calc( 1.7 * var(--ck-line-height-base) * var(--ck-font-size-base) );
		min-width: 6em;
	}

	/* Scale down all heading previews because they are way too big to be presented in the UI.
	Preserve the relative scale, though. */
	.document-editor .ck-heading-dropdown .ck-list .ck-heading_heading1 .ck-button__label,
	.document-editor .ck-heading-dropdown .ck-list .ck-heading_heading2 .ck-button__label {
		transform: scale(0.8);
		transform-origin: left;
	}

	/* Set the styles for "Heading 1". */
	.document-editor .ck-content h2,
	.document-editor .ck-heading-dropdown .ck-heading_heading1 .ck-button__label {
		font-size: 2.18em;
		font-weight: normal;
	}

	.document-editor .ck-content h2 {
		line-height: 1.37em;
		padding-top: .342em;
		margin-bottom: .142em;
	}

	/* Set the styles for "Heading 2". */
	.document-editor .ck-content h3,
	.document-editor .ck-heading-dropdown .ck-heading_heading2 .ck-button__label {
		font-size: 1.75em;
		font-weight: normal;
		color: hsl( 203, 100%, 50% );
	}

	.document-editor .ck-heading-dropdown .ck-heading_heading2.ck-on .ck-button__label {
		color: var(--ck-color-list-button-on-text);
	}

	/* Set the styles for "Heading 2". */
	.document-editor .ck-content h3 {
		line-height: 1.86em;
		padding-top: .171em;
		margin-bottom: .357em;
	}

	/* Set the styles for "Heading 3". */
	.document-editor .ck-content h4,
	.document-editor .ck-heading-dropdown .ck-heading_heading3 .ck-button__label {
		font-size: 1.31em;
		font-weight: bold;
	}

	.document-editor .ck-content h4 {
		line-height: 1.24em;
		padding-top: .286em;
		margin-bottom: .952em;
	}

	/* Make the block quoted text serif with some additional spacing. */
	.document-editor .ck-content blockquote {
		font-family: Georgia, serif;
		margin-left: calc( 2 * var(--ck-spacing-large) );
		margin-right: calc( 2 * var(--ck-spacing-large) );
	}

	@media only screen and (max-width: 960px) {
		/* Because on mobile 2cm paddings are to big. */
		.document-editor__editable-container .document-editor__editable.ck-editor__editable {
			padding: 1.5em;
		}
	}

	@media only screen and (max-width: 1200px) {
		.main__content-wide .document-editor__editable-container .document-editor__editable.ck-editor__editable {
			width: 100%;
		}
	}

	/* Style document editor a'ka Google Docs.*/
	@media only screen and (min-width: 1360px) {
		.main .main__content.main__content-wide {
			padding-right: 0;
		}
	}

	@media only screen and (min-width: 1600px) {
		.main .main__content.main__content-wide {
			width: 24cm;
		}

		.main .main__content.main__content-wide .main__content-inner {
			width: auto;
			margin: 0 50px;
		}

		/* Keep "page" look based on viewport width. */
		.main__content-wide .document-editor__editable-container .document-editor__editable.ck-editor__editable {
			width: 60%;
		}
	}
</style>

以上就是如何在vue中使用ckeditor5的方法,当然官方也有专门针对vue和react的ckeditor组件,你可以直接拿来使用。ckeditor5-react,ckeditor5-vue,ckeditor5-angular

效果图如下

在这里插入图片描述

ckeditor4

ckeditor4也有多种模式,为什么这里还需要讲ckeditor4呢,因为上面的ckeditor5更符合现代的web工程,但是却有一些功能暂时还没有解决,比如复制word文档图文,图片有的无法上传,还有一个就是对于wps文档的复制目前是有问题的,此时通过降级可以避免大多数问题。具体使用就直接自行查看官方文档。当然ckeditor4也有专门针对三大框架的版本ckeditor4-reactckeditor4-vueckeditor4-angular 使用方式就不论述了,为什么不直接使用这些呢,是为了更容易的添加插件,更好的自定义自己的富文本编辑器。

ckeditor4官方文档

下载

你可以在官网找到下载页面,下载地址

官网有多种版本下载Basic Package,Standard Package,Full Package,Customize。自行根据现需要下载相应的版本。

vue中使用ckeditor4

在我们下载的ckeditor4完整文件中,我们打开toolbarconfigurator页面可以可视化配置toolbar的显示,可以增加删除调整顺序等,然后可以获取配置,把配置复制下来保存到之前下载的config文件中。
在这里插入图片描述

  1. 将下载的ckeditor整个文件夹放在项目的public目录下

  2. 在public的index.html文件中引入相应的文件

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <title><%= webpackConfig.name %></title>
        <script src="<%= BASE_URL %>ckeditor/ckeditor.js"></script>
      </head>
      <body>
        <noscript>
          <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    
    
    1. 自定义上传图片,我们可以在fileUploadRequest事件出发的时候自定义上传方法,可以在fileUploadResponse上传成功后自定义上传成功的方法
    完整代码
    <template>
      <div class="rich-container">
        <div class="rich-editor document-editor">
          <textarea id="editor" />
        </div>
        <el-button type="primary" size="mini" @click="getContent">获取内容</el-button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'Dashboard',
      data() {
        return {
          editor: null
        }
      },
      mounted() {
        this.initEditor()
      },
      methods: {
        initEditor() {
          this.editor = window.CKEDITOR.replace('editor', {
            height: 600,
            bodyClass: 'document-editor'
          })
          window.CKEDITOR.on('instanceReady', e => {
            console.log('ckeditor初始化', e)
            const upload = e.editor.uploadRepository
            upload.on('instanceCreated', function(eve) {
              console.log('创建了')
            })
            e.editor.on('change', function(change) {
              console.log('change', change)
            })
            e.editor.on('fileUploadRequest', (evt) => {
              const fileLoader = evt.data.fileLoader
              const formData = new FormData()
              const xhr = fileLoader.xhr
              fileLoader.uploadUrl = '/services/businessservice/api/attachments/uploadFile' // 上传文件接口地址
              xhr.open('post', fileLoader.uploadUrl, true)
              formData.append('file', fileLoader.file, fileLoader.fileName)
              fileLoader.xhr.send(formData)
              // Prevented the default behavior.
              evt.stop()
              // 上传
            })
            e.editor.on('fileUploadResponse', (evt) => {
              evt.stop()
              const data = evt.data
              const xhr = data.fileLoader.xhr
              const response = xhr.responseText
              const res = JSON.parse(response)
              if (res.meta.code === 200) {
                data.message = res.meta.message
                data.url =  res.data.url // 上传图片成功后返回的图片路径
              }
            })
          })
        },
        getContent() {
          console.log(this.editor.getData())
        }
    
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .rich-editor {
      width: 60%;
      min-height: 500px;
      margin: 20px auto;
    }
    </style>
    
    

    效果图如下:

在这里插入图片描述

使用ckeditor4解决了二word图文复制以及wps文档的复制问题,不过还有一个问题没有解决,就是wps中的图片复制问题。

关于获取富文本编辑器内容,以及设置内容的方法ckeditor4和ckeditor5都是一样的,先获取editor实例然后调用其方法

  1. 获取编辑器内容: getData()

  2. 获取编辑器内容: setData()

Logo

前往低代码交流专区

更多推荐