Contribute to this guide

guide自动保存

自动保存功能允许您在需要时自动保存数据(例如,将其发送到服务器)。例如,这可能发生在用户更改内容时。

# 演示

在下面的演示中输入一些文本以尝试自动保存功能。尝试添加诸如图像或表格之类的富文本内容,并观察功能的行为。演示元素和机制在编辑器下方解释。

输入一些文本或输入一些富文本内容以测试自动保存功能。

状态
HTTP 服务器延迟 (ms)

服务器数据

Type some text or input some rich content to test the autosave feature.

如何理解此演示

  • 状态指示器显示编辑器是否有未保存的内容或待处理的操作。
    • 如果您将一张大图像放到此编辑器中,您会看到在整个图像上传过程中它都是繁忙的。
    • 在保存内容正在进行时,编辑器也会处于繁忙状态(save() 的 Promise 尚未解析)。
  • 自动保存功能具有节流机制,可以将频繁更改(如打字)分组到批次中。
  • 自动保存本身不检查数据是否实际上已更改。它基于模型中的更改,这些更改有时可能在数据中不可见。如果您希望避免将相同的数据两次发送到服务器,您可以自己添加此类检查。
  • 如果您正在上传图像或数据尚未成功保存,系统会询问您是否要离开页面。您可以通过将一张大图像放到编辑器中或将“HTTP 服务器延迟”更改为高值(例如 9000 毫秒)并输入一些内容来测试这一点。这些操作将使编辑器繁忙更长时间——然后尝试离开页面。

此演示展示了一组有限的功能。访问功能丰富的编辑器示例以查看更多实际应用。

# 安装

⚠️ 新的导入路径

版本 42.0.0 开始,我们更改了导入路径的格式。本指南使用新的、更短的格式。如果您使用的是旧版本的 CKEditor 5,请参考旧版设置中的包指南。

安装编辑器后,将功能添加到插件列表中。

假设您已实现某种形式的 saveData() 函数,该函数将数据发送到您的服务器并返回一个 Promise,该 Promise 在数据成功保存后解析,那么配置Autosave 功能很简单

import { ClassicEditor, Autosave } from 'ckeditor5';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [
            Autosave,

            // ... other plugins.
        ],

        autosave: {
            save( editor ) {
                return saveData( editor.getData() );
            }
        },

        // ... other configuration options.
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

自动保存功能监听editor.model.document#change:data 事件,对它进行节流,并执行config.autosave.save() 函数。

它还监听本机window#beforeunload 事件,并在以下情况下阻止它

  • 数据尚未保存(save() 函数尚未解析其 Promise 或由于节流而尚未被调用)。
  • 或者编辑器中的任何功能都注册了“待处理操作”(例如,正在上传图像)。

这会自动确保您不会在内容保存之前或某些正在进行的操作(如图像上传)未完成之前离开页面。

# 配置

您可以使用config.waitingTime 属性配置两次保存操作之间的最小间隔。这有助于避免过度加载后端。

如果在上次保存编辑器数据后没有任何更改,则默认情况下两次保存操作之间的等待时间为一秒。

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        autosave: {
            waitingTime: 5000, // in ms
            save( editor ) {}
        },

        // ... other configuration options.
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

# 演示代码

本指南开头处的演示示例展示了编辑器与一个假 HTTP 服务器的简单集成(该服务器需要 1000 毫秒来保存内容)。以下是演示代码

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [
            Autosave,

            // ... other plugins.
        ],

        autosave: {
            save( editor ) {
                return saveData( editor.getData() );
            }
        }
    } )
    .then( editor => {
        window.editor = editor;

        displayStatus( editor );
    } )
    .catch( err => {
        console.error( err.stack );
    } );

// Save the data to a fake HTTP server (emulated here with a setTimeout()).
function saveData( data ) {
    return new Promise( resolve => {
        setTimeout( () => {
            console.log( 'Saved', data );

            resolve();
        }, HTTP_SERVER_LAG );
    } );
}

// Update the "Status: Saving..." information.
function displayStatus( editor ) {
    const pendingActions = editor.plugins.get( 'PendingActions' );
    const statusIndicator = document.querySelector( '#editor-status' );

    pendingActions.on( 'change:hasAny', ( evt, propertyName, newValue ) => {
        if ( newValue ) {
            statusIndicator.classList.add( 'busy' );
        } else {
            statusIndicator.classList.remove( 'busy' );
        }
    } );
}

您可以在入门部分中阅读更多关于获取和设置数据的信息。

# 通用 API

Autosave 插件注册用于保存数据的AutosaveAdapter

您可以使用AutosaveConfig 来控制适配器的行为。

# 贡献

该功能的源代码在 GitHub 上的https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-autosave 上可用。