Contribute to this guide

guideVue.js 3+ 富文本编辑器组件

npm version

Vue.js 是一个用于构建 Web 用户界面的通用框架。CKEditor 5 提供了您可以应用程序中使用的官方 Vue 组件。

CKEditor 5 构建器

在我们的交互式构建器中,您可以快速体验 CKEditor 5。它提供了一个易于使用的用户界面,可帮助您配置、预览和下载适合您需求的编辑器。您可以轻松选择

  • 编辑器类型。
  • 您需要的功能。
  • 首选框架(React、Angular、Vue 或 Vanilla JS)。
  • 首选分发方式。

最后,您将获得适合您需求的现成代码!

查看我们的交互式构建器

# 快速入门

# 设置项目

本指南假定您已经拥有一个 Vue 项目。如果您没有,请查看 Vue 文档 了解如何创建它。

# 安装

首先安装以下软件包

  • ckeditor5 - 包含 CKEditor 5 的所有开源插件和功能。

    npm install ckeditor5
    
  • ckeditor5-premium-features - 包含 CKEditor 5 的高级插件和功能。根据您的配置和所选插件,您可能不需要它。

    npm install ckeditor5-premium-features
    
  • @ckeditor/ckeditor5-vue - CKEditor 5 用于 Vue 的 WYSIWYG 编辑器组件

    npm install @ckeditor/ckeditor5-vue
    

安装完这些软件包后,您现在需要选择是全局安装还是本地安装 <ckeditor> 组件,并按照以下相应说明操作。

# 全局安装 <ckeditor> 组件

要全局注册 <ckeditor> 组件,您必须安装 CKEditor 5 的 Vue 插件。

如果您使用的是一个简单的 Vue 项目,您应该找到调用 createApp 函数的文件,并使用 use() 方法 注册 CkeditorPlugin 插件。

import { createApp } from 'vue';
import { CkeditorPlugin } from '@ckeditor/ckeditor5-vue';
import App from './App.vue';

createApp( App )
    .use( CkeditorPlugin )
    .mount( '#app' );

如果您使用的是 Nuxt.js,您可以按照 Nuxt.js 文档 获取 use() 方法并注册此插件。

现在,您可以在任何 Vue 组件中使用 <ckeditor> 组件。以下示例显示了一个具有开源和高级插件的单文件组件。

<template>
    <div id="app">
        <ckeditor
            v-model="editorData"
            :editor="editor"
            :config="editorConfig"
        />
    </div>
</template>

<script>
import { ClassicEditor, Bold, Essentials, Italic, Mention, Paragraph, Undo } from 'ckeditor5';
import { SlashCommand } from 'ckeditor5-premium-features';

import 'ckeditor5/ckeditor5.css';
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';

export default {
    name: 'app',
    data() {
        return {
            editor: ClassicEditor,
            editorData: '<p>Hello from CKEditor 5 in Vue!</p>',
            editorConfig: {
                plugins: [ Bold, Essentials, Italic, Mention, Paragraph, SlashCommand, Undo ],
                toolbar: [ 'undo', 'redo', '|', 'bold', 'italic' ],
                licenseKey: '<YOUR_LICENSE_KEY>',
                // Other configuration options...
            }
        };
    }
};
</script>

# 在本地使用 <ckeditor> 组件

如果您不想全局启用 CKEditor 5 组件,您可以直接从 @ckeditor/ckeditor5-vue 包中导入 Ckeditor 组件到您想要使用它的 Vue 组件中,并将它添加到 components 对象中。

<template>
    <div id="app">
        <ckeditor
            v-model="editorData"
            :editor="editor"
            :config="editorConfig"
        />
    </div>
</template>

<script>
import { ClassicEditor, Bold, Essentials, Italic, Mention, Paragraph, Undo } from 'ckeditor5';
import { SlashCommand } from 'ckeditor5-premium-features';
import { Ckeditor } from '@ckeditor/ckeditor5-vue';

import 'ckeditor5/ckeditor5.css';
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';

export default {
    name: 'app',
    components: {
        Ckeditor
    },
    data() {
        return {
            editor: ClassicEditor,
            editorData: '<p>Hello from CKEditor 5 in Vue!</p>',
            editorConfig: {
                plugins: [ Bold, Essentials, Italic, Mention, Paragraph, SlashCommand, Undo ],
                toolbar: [ 'undo', 'redo', '|', 'bold', 'italic' ],
                licenseKey: '<YOUR_LICENSE_KEY>',
                // Other configuration options...
            }
        };
    }
};
</script>

# 组件指令

# editor

此指令指定要由组件使用的编辑器。它必须直接引用要在模板中使用的编辑器构造函数。

<template>
    <div id="app">
        <ckeditor :editor="editor" />
    </div>
</template>

<script>
    import { ClassicEditor } from 'ckeditor5';

    export default {
        name: 'app',
        data() {
            return {
                editor: ClassicEditor,

                // ...
            };
        }
    };
</script>

# tag-name

默认情况下,编辑器组件会创建一个 <div> 容器,该容器用作传递给编辑器的元素(例如,ClassicEditor#element)。可以配置该元素,例如,要创建一个 <textarea>,请使用以下指令

<ckeditor :editor="editor" tag-name="textarea" />

# v-model

Vue 中用于表单输入的 标准指令。与 model-value 不同,它创建了一个双向数据绑定,它

  • 设置初始编辑器内容。
  • 当编辑器内容发生变化时(例如,用户键入时)自动更新应用程序状态。
  • 可用于在必要时设置编辑器内容。
<template>
    <div id="app">
        <ckeditor :editor="editor" v-model="editorData" />
        <button @click="emptyEditor">Empty the editor</button>

        <h2>Editor data</h2>
        <code>{{ editorData }}</code>
    </div>
</template>

<script>
    import { ClassicEditor } from 'ckeditor5';

    export default {
        name: 'app',
        data() {
            return {
                editor: ClassicEditor,
                editorData: '<p>Content of the editor.</p>'
            };
        },
        methods: {
            emptyEditor() {
                this.editorData = '';
            }
        }
    };
</script>

在上面的示例中,editorData 属性将在用户键入和内容发生变化时自动更新。它还可用于更改(如 emptyEditor() 中)或设置编辑器的初始内容。

如果您只想在编辑器数据发生变化时执行操作,请使用 input 事件。

# model-value

允许单向数据绑定,该绑定设置编辑器的内容。与 v-model 不同,当编辑器的内容发生变化时,该值不会更新。

<template>
    <div id="app">
        <ckeditor :editor="editor" :model-value="editorData" />
    </div>
</template>

<script>
    import { ClassicEditor } from 'ckeditor5';

    export default {
        name: 'app',
        data() {
            return {
                editor: ClassicEditor,
                editorData: '<p>Content of the editor.</p>'
            };
        }
    };
</script>

要执行编辑器数据发生变化时的操作,请使用 input 事件。

# config

指定编辑器的 配置

<template>
    <div id="app">
        <ckeditor :editor="editor" :config="editorConfig" />
    </div>
</template>

<script>
    import { ClassicEditor } from 'ckeditor5';

    export default {
        name: 'app',
        data() {
            return {
                editor: ClassicEditor,
                editorConfig: {
                    toolbar: [ 'bold', 'italic', '|', 'link' ]
                }
            };
        }
    };
</script>

# disabled

此指令控制编辑器的 isReadOnly 属性。

它设置编辑器的初始只读状态,并在其生命周期中进行更改。

<template>
    <div id="app">
        <ckeditor :editor="editor" :disabled="editorDisabled" />
    </div>
</template>

<script>
    import { ClassicEditor } from 'ckeditor5';

    export default {
        name: 'app',
        data() {
            return {
                editor: ClassicEditor,
                // This editor will be read–only when created.
                editorDisabled: true
            };
        }
    };
</script>

# disableTwoWayDataBinding

允许禁用双向数据绑定机制。默认值为 false

引入此选项的原因是大文档中的性能问题。启用此标志后,v-model 指令将不再在编辑器数据发生变化时更新连接的值。

此选项允许集成者禁用默认行为,并且仅在需要时调用 editor.getData() 方法,从而防止速度变慢。您可以在 相关问题 中了解更多信息。

<ckeditor :editor="editor" :disableTwoWayDataBinding="true" />

# 组件事件

# ready

对应于 ready 编辑器事件。

<ckeditor :editor="editor" @ready="onEditorReady" />

# focus

对应于 focus 编辑器事件。

<ckeditor :editor="editor" @focus="onEditorFocus" />

# blur

对应于 blur 编辑器事件。

<ckeditor :editor="editor" @blur="onEditorBlur" />

# input

对应于 change:data 编辑器事件。

<ckeditor :editor="editor" @input="onEditorInput" />

# destroy

对应于 destroy 编辑器事件。

注意:由于编辑器的销毁是基于承诺的,因此此事件可能在实际承诺解决之前触发。

<ckeditor :editor="editor" @destroy="onEditorDestroy" />

# 如何?

# 使用 Document 编辑器类型

如果您在应用程序中使用 Document(分离)编辑器,则需要 手动将编辑器工具栏添加到 DOM 中

由于在编辑器实例 准备好之前无法访问编辑器工具栏,因此请将工具栏插入代码放在组件的 ready 事件触发时执行的方法中,如以下示例所示

<template>
    <div id="app">
        <ckeditor :editor="editor" @ready="onReady" />
    </div>
</template>

<script>
    import { DecoupledEditor, Bold, Essentials, Italic, Paragraph, Undo } from 'ckeditor5';
    import CKEditor from '@ckeditor/ckeditor5-vue';

    import 'ckeditor5/ckeditor5.css';

    export default {
        name: 'app',
        data() {
            return {
                editor: DecoupledEditor,
                // ...
            };
        },
        methods: {
            onReady( editor )  {
                // Insert the toolbar before the editable area.
                editor.ui.getEditableElement().parentElement.insertBefore(
                    editor.ui.view.toolbar.element,
                    editor.ui.getEditableElement()
                );
            }
        }
    };
</script>

# 使用与协作插件的编辑器

我们提供了一个**现成的集成**,它在 Vue 应用程序中具有协作编辑功能

它不是必须在上述示例的基础上构建应用程序,但它应该可以帮助您入门。

# 本地化

CKEditor 5 支持 多种 UI 语言,官方 Vue 组件也一样。按照以下说明在您的 Vue 应用程序中翻译 CKEditor 5。

与 CSS 样式表类似,这两个软件包都有单独的翻译。按照以下示例导入它们。然后,将它们传递给组件中 editorConfig 属性内的 translations 数组

<template>
    <div id="app">
        <ckeditor :editor="editor" v-model="editorData" :config="editorConfig" />
    </div>
</template>

<script>
import { ClassicEditor, Bold, Essentials, Italic, Paragraph } from 'ckeditor5';
// More imports...

import coreTranslations from 'ckeditor5/translations/es.js';
import premiumFeaturesTranslations from 'ckeditor5-premium-features/translations/es.js';

// Style sheets imports...

export default {
    name: 'app',
    data() {
        return {
            editor: ClassicEditor,
            editorData: '<p>Hola desde CKEditor 5 en Vue!</p>',
            editorConfig: {
                toolbar: {
                    items: [ 'undo', 'redo', '|', 'bold', 'italic' ],
                },
                plugins: [ Bold, Essentials, Italic, Paragraph ],
                translations: [ coreTranslations, premiumFeaturesTranslations ]
            }
        };
    }
};
</script>

有关更多信息,请参阅 设置 UI 语言 指南。

# Jest 测试

您可以在 Vue 应用程序中使用 Jest 作为测试运行器。不幸的是,Jest 不会使用真正的浏览器。相反,它会在 Node.js 中运行测试,该测试使用 JSDOM。JSDOM 不是完整的 DOM 实现,虽然它足以用于标准应用程序,但它无法模拟 CKEditor 5 所需的所有 DOM API。

为了测试 CKEditor 5,建议使用利用真实浏览器并提供完整 DOM 实现的测试框架。一些流行的选择包括

这些框架为测试 CKEditor 5 提供了更好的支持,并更准确地反映了编辑器在真实浏览器环境中的行为。

如果无法做到这一点,并且仍然想要使用 Jest,则可以模拟一些必需的 API。以下是模拟 CKEditor 5 使用的一些 API 的示例

beforeAll( () => {
    window.scrollTo = jest.fn();

    window.ResizeObserver = class ResizeObserver {
        observe() {}
        unobserve() {}
        disconnect() {}
    };

    for (const key of ['InputEvent', 'KeyboardEvent']) {
        window[key].prototype.getTargetRanges = () => {
            const range = new StaticRange({
                startContainer: document.body.querySelector('.ck-editor__editable p')!,
                startOffset: 0,
                endContainer: document.body.querySelector('.ck-editor__editable p')!,
                endOffset: 0,
            });

            return [range];
        };
    }

    Range.prototype.getClientRects = () => ({
        item: () => null,
        length: 0,
        [Symbol.iterator]: function* () {},
    });
} );

这些模拟应该放在使用 CKEditor 5 的测试之前。它们并不完美,可能无法涵盖所有情况,但它们应该足以用于基本初始化和渲染编辑器。请记住,它们不能替代适当的浏览器测试。

# 贡献与报告问题

该组件的源代码在 GitHub 上的 https://github.com/ckeditor/ckeditor5-vue 中可用。