本节涵盖:

  • 使用 NPM 或 Yarn 安装 TinyMCE React 集成

  • 在 Bootstrap 对话框中使用 TinyMCE React 集成

  • 配置编辑器

  • 可用属性

    • apiKey

    • licenseKey

    • cloudChannel

    • disabled

    • readonly

    • id

    • init

    • initialValue

    • inline

    • onEditorChange

    • outputFormat (已移除)

    • plugins

    • rollback

    • scriptLoading

    • tagName

    • textareaName

    • toolbar

    • tinymceScriptSrc

    • value

    • tabIndex

  • 将 TinyMCE React 组件用作非受控组件

  • 将 TinyMCE React 组件用作受控组件

  • 事件绑定

使用 NPM 或 Yarn 安装 TinyMCE React 集成

要安装 tinymce-react 包并将其保存到 package.json 中。

npm install @tinymce/tinymce-react

或使用 Yarn

yarn add @tinymce/tinymce-react

在 Bootstrap 对话框中使用 TinyMCE React 集成

要在 Bootstrap UI 对话框内部使用 TinyMCE React 集成,请向渲染编辑器的组件添加以下 React 效果钩子。此代码是必需的,因为 Bootstrap 会阻止来自对话框外部元素的 focusin 调用。

Bootstrap 5

对于 Bootstrap 5,React 效果钩子不包含 JQuery。
useEffect(() => {
  const handler = (e) => {
    if (e.target.closest(".tox-tinymce-aux, .moxman-window, .tam-assetmanager-root") !== null) {
      e.stopImmediatePropagation();
    }
  };
  document.addEventListener("focusin", handler);
  return () => document.removeEventListener("focusin", handler);
}, []);

Bootstrap 4

useEffect(function() {
  var handler = function(e) {
    if ($(e.target).closest(".tox-tinymce, .tox-tinymce-aux, .moxman-window, .tam-assetmanager-root").length) {
      e.stopImmediatePropagation();
    }
  };
  $(document).on('focusin', handler);
  return function() {
    $(document).off('focusin', handler);
  };
}, []);

配置编辑器

tinymce-react 组件提供以下属性的 props:

  • 配置编辑器源

  • 配置页面元素

  • 配置编辑器选项

  • 管理编辑器

配置编辑器源

tinymce-react 集成将按以下顺序尝试获取 TinyMCE 源:

  1. 如果页面上存在全局 tinymce,则使用该 tinymce。

  2. 如果提供了 tinymceScriptSrc prop,则将向页面添加一个脚本标签,以便从给定的 URL 加载 TinyMCE。

  3. 如果上述条件均不适用,则将向页面添加一个脚本标签,以便从 Tiny Cloud 加载 TinyMCE。

以下 props 用于配置如何获取编辑器源:

apiKey

Tiny Cloud API 密钥。当从 Tiny Cloud 加载时,使用此 prop 以移除“继续使用 TinyMCE 需要有效的 API 密钥。请通知管理员检查当前 API 密钥。点击此处了解更多。”警告消息。

licenseKey

Tiny Cloud 许可密钥。如果您自行托管 TinyMCE 而不是从 Tiny Cloud 加载时使用此密钥。

cloudChannel

当从 Tiny Cloud 加载时使用的 TinyMCE 通道。

scriptLoading

脚本加载行为 prop。允许设置 async 和 defer 属性,以及添加额外的毫秒延迟。

tinymceScriptSrc

当加载自托管版本的 TinyMCE 时用于获取 TinyMCE 的 URL。

配置页面元素

这些 props 提供一些对集成创建的页面元素的控制:

id

编辑器初始化所在元素的 id 属性。

inline

将编辑器作为页面的一部分加载;共享页面样式和选择范围。

tagName

用于创建内联编辑器的标签。对于经典(iframe)编辑器将被忽略。

textareaName

textarea 标签(HTML 元素)的 name 属性。用于创建经典(iframe)编辑器。对于内联编辑器将被忽略。

配置编辑器选项

这些 props 在编辑器初始化时被读取。编辑器启动后的更改将被忽略。

init

传递给 TinyMCE 的附加选项,在其初始化时生效。

plugins

指定编辑器插件。这将与 init prop 中的 plugins 合并。

toolbar

指定编辑器工具栏。这将覆盖 init prop 中的 toolbar。

管理编辑器

这些 props 可以在编辑器初始化后更新。注意此处未提及其它事件。

disabled

是否禁用编辑器。

readonly

是否将编辑器设置为只读模式。

initialValue

编辑器的初始值。在编辑器加载后更改此值将重置编辑器(包括编辑器内容)。

onBeforeAddUndo

一个事件处理器,用于通知何时即将创建撤销级别,并在需要时阻止它。这对于限制编辑器允许值的受控组件非常重要。

onEditorChange

一个事件处理器,用于检测编辑器更改。在将 TinyMCE 实现为受控组件时非常有用。

onInit

一个事件处理器,用于通知编辑器已初始化。适用于获取编辑器的初始值或获取可用于非受控组件的编辑器引用。

value

设置并强制执行编辑器的值。仅用于受控组件。

value

设置编辑器包裹的目标元素的 tabindex。

可用 props

TinyMCE React 组件不需要任何配置 props;但是,如果从 Tiny Cloud 加载时未配置 apiKey prop,编辑器中将显示警告消息。关于使用哪些 props 的指导,请参阅:配置编辑器。

apiKey

Tiny Cloud API 密钥。

对于使用 Tiny Cloud 部署以提供 TinyMCE 编辑器且不希望显示警告消息"A valid API key is required to continue using TinyMCE. Please alert the admin to check the current API key. Click here to learn more"的情况,此密钥是必需的。

要注册 Tiny Cloud API 密钥,请访问 Tiny Account 注册页面。要为现有的 Tiny Account 检索 Tiny Cloud API 密钥,请登录并访问 Tiny Account 仪表板。

类型: String

默认值: 'no-api-key'

示例:使用 apiKey

<Editor
  apiKey='no-api-key'
/>

licenseKey

指定 TinyMCE 许可密钥。对于 TinyMCE 的自托管部署是必需的。对于仅使用 Tiny Cloud 的云部署,此属性不是必需的,因为您的云订阅自动包含商业许可。更多信息,请参阅:License Key。

类型: String

默认值: undefined

可能值:* undefined - 当使用 API 密钥从 Tiny Cloud 加载时使用* 'gpl' - 用于使用 GPL 许可的开源项目* 'T8LK:…​' - 用于商业 TinyMCE 安装(版本 8+ 必须使用此前缀)* 'GPL+T8LK:' - 用于需要高级功能但需保持 GPL 合规性的开源项目。

在混合部署(同时使用云和自托管功能)中:

  • 您可以同时提供 API 密钥和许可密钥

  • 编辑器将在可用时使用云服务

  • 如果无法联系云服务,它将自动回退到本地许可密钥

示例:商业许可

<Editor
  licenseKey='T8LK:...'
/>

示例:使用带有 GPL 的 licenseKey

<Editor
  licenseKey='gpl'
/>

cloudChannel

更改用于编辑器的 TinyMCE 构建版本,可以是特定版本或表示稳定级别的通道。

类型: String

默认值: '8'

可能值: '8', '8-testing', '8-dev', '8.10'

更改用于编辑器的 TinyMCE 构建版本,使其为以下 Tiny Cloud 频道之一:

  • 8(默认值):TinyMCE 当前的企业版发布。

  • 8-testing:TinyMCE 下一代企业版发布的当前候选版本。

  • 8-dev:TinyMCE 的夜间构建版本。

  • 版本号,例如 8.10:TinyMCE 特定的企业版发布版本。

例如:

<Editor
  apiKey='no-api-key'
  cloudChannel='8-dev'
  init={{ /* your other settings */ }}
/>

有关 TinyMCE 开发频道的信息,请参阅:指定从 Cloud 部署的 TinyMCE 编辑器版本 - dev、testing 和 stable 发布。

disabled

disabled 属性可以动态切换编辑器的禁用状态。

类型: Boolean

默认值: false

可能值: true, false

示例:使用 disabled

<Editor
  disabled={true}
/>

readonly

readonly 属性可以在只读模式(true)和标准可编辑模式(false)之间动态切换编辑器。

类型: Boolean

默认值: false

可能值: true, false

示例:使用 readonly

<Editor
  readonly={true}
/>

id

编辑器的 ID。用于通过 tinymce.get('ID') 方法检索编辑器实例。

类型: String

默认值: 自动生成 UUID

示例:使用 id

<Editor
  id='your-id'
/>

init

传递给 tinymce.init({...}) 方法的附加设置,该方法用于初始化编辑器。

有关 TinyMCE tinymce.init({...}) 方法的信息,请参阅:基本设置。

当使用 tinymce-react 时:

  • init 属性不需要 selector 或 target 选项。

  • 如果使用 init 属性设置了 selector、target、readonly 或 license_key 选项,它们将被集成覆盖。

类型: Object

默认值: { }

示例:使用 init

<Editor
  init={{
    plugins: 'lists link image paste help wordcount',
    toolbar: 'undo redo | blocks | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | help'
  }}
/>

initialValue

编辑器的初始 HTML 内容。更改此值将重置编辑器的撤销状态和光标位置。

可以在编辑器加载之前设置,也可以在随后由异步过程设置。

请确保此值不要通过 onEditorChange 更新,否则编辑器将无法使用。

类型: String

默认值: ''

示例:使用静态 initialValue

<Editor
  initialValue='<p>Once upon a time...</p>'
/>

示例:使用异步 initialValue

const [initialValue, setInitialValue] = useState(undefined);
useEffect(() => {
  // 实际应用中可能会在此处执行 fetch 请求以获取内容
  setTimeout(() => setInitialValue('<p>Once upon a time...</p>'), 500);
}, []);

return (
  <Editor
    initialValue={initialValue}
  />
);

inline

用于将编辑器设置为内联模式。使用 <Editor inline={true} /> 等同于在 TinyMCE tinymce.init({...}) 方法中设置 {inline: true}。

有关内联模式的信息,请参见:用户界面选项 - inline 和 设置内联编辑模式。

类型: Boolean

默认值: false

可能值: true, false

示例:使用 inline

<Editor
  inline={true}
/>

onEditorChange

用于在 TinyMCE React 组件外部存储编辑器状态。当将 TinyMCE React 组件用作受控组件时,通常会使用此属性。

它接收两个参数:

value

编辑器的当前值。这是 HTML 格式。

editor

对编辑器的引用。

有关使用 onEditorChange 的详细信息,请参见:将 TinyMCE React 组件用作受控组件。

类型: EventHandler

outputFormat (已移除)

此选项已在 TinyMCE React 组件 4.0.0 版本发布时被移除。

此选项用于指定由onEditorChange事件生成的内容的格式,但由于它不改变输入格式,因此几乎无法正确使用。

示例:替换 outputFormat 的使用

const [value, setValue] = useState('<p>The quick brown fox jumps over the lazy dog</p>');
const [text, setText] = useState('');

return (
  <>
    <Editor
      value={value}
      onInit={(evt, editor) => {
        setText(editor.getContent({format: 'text'}));
      }}
      onEditorChange={(newValue, editor) => {
        setValue(newValue);
        setText(editor.getContent({format: 'text'}));
      }}
    />
    <pre>{text}</pre>
  </>
);

plugins

用于包含编辑器的插件。使用 <Editor plugins='lists' /> 等同于在 TinyMCE tinymce.init({...}) 方法中设置 {plugins: 'lists'}。

有关向 TinyMCE 添加插件的信息,请参见:向 TinyMCE 添加插件。

类型: String 或 Array

示例:使用 plugins

<Editor
  plugins='lists code'
/>

rollback

用于配置回滚计时器。这是在 onEditorChange 属性发出事件与强制应用 value 属性之间的毫秒数。

当 rollback 为 false 时,除非 value 属性发生变化,否则不会强制应用该属性。

类型: Number 或 false

默认值: 200

示例:使用 rollback

<Editor
  rollback={0}
  value="<p>This value will be restored almost as soon as it is changed.</p>"
/>

scriptLoading

用于配置用于加载 TinyMCE 的 script 标签。

类型: Object

type ScriptLoading = {
  async?: boolean;
  defer?: boolean;
  delay?: number;
};

包含 3 个设置:

async

设置在用于加载 TinyMCE 的 script 标签上的 async 属性。

对于传统脚本,如果存在 async 属性,则传统脚本将与解析并行获取,并在可用时立即执行。
— https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async

类型: Boolean

默认值: false

defer

设置在用于加载 TinyMCE 的 script 标签上的 defer 属性。

此 Boolean 属性用于指示浏览器在文档解析完成后但在触发 DOMContentLoaded 之前执行脚本。
— https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer

类型: Boolean

默认值: false

delay

将在指定的毫秒延迟后添加用于加载 TinyMCE 的 script 标签。

类型: Number

默认值: 0

示例:异步加载 TinyMCE

<Editor scriptLoading={{ async: true }}>

示例:延迟 500 毫秒加载 TinyMCE

<Editor scriptLoading={{ delay: 500 }}>

tagName

仅在 <Editor inline={true} /> 时有效。用于定义内联模式下编辑器的 HTML 元素。

类型: String

默认值: 'div'

示例:使用 tagName

<Editor
  inline={true}
  tagName='section'
/>

textareaName

仅在编辑器处于经典(iframe)模式时有效。设置表单中用于编辑器的 textarea 元素的 name 属性。

类型: String

示例:使用 textareaName

<form method="post">
  <Editor
    textareaName='description'
  />
  <button type="submit">提交</button>
</form>

toolbar

用于设置编辑器的工具栏。使用 <Editor toolbar='bold' /> 等同于在 TinyMCE 方法 tinymce.init({...}) 中设置 {toolbar: 'bold'}。

有关设置 TinyMCE 工具栏的信息,请参阅:用户界面选项 - 工具栏。

类型: String

可能值: 请参阅 TinyMCE 可用的工具栏按钮。

示例:使用 toolbar

<Editor
  plugins='code'
  toolbar='bold italic underline code'
/>

tinymceScriptSrc

使用 tinymceScriptSrc 属性指定要懒加载的 TinyMCE 外部版本。

类型: String

示例:使用 tinymceScriptSrc

<Editor
  tinymceScriptSrc='/path/to/tinymce.min.js'
/>

value

当作为受控组件运行时,设置编辑器的 HTML 内容。

当此属性与当前编辑器内容不同时,编辑器内容将在 200 毫秒内更改以匹配,并创建一个撤销级别。当通过此机制更改编辑器内容时,编辑器将尝试保留选择状态,但如果新内容中不存在之前的选择,光标将返回到文档开头。

此属性允许通过设置 value 属性并使用 onEditorChange 事件更新 value 来将编辑器用作受控组件。

有关使用 value 属性的详细信息,请参阅:将 TinyMCE React 组件用作受控组件。

类型: String

tabIndex

使用 tabIndex 属性设置编辑器包装的目标元素的 tabindex。

类型: Number

示例:使用 tabIndex

<Editor
  tabIndex={-1}
/>

将 TinyMCE React 组件用作非受控组件

TinyMCE React 组件设计为用作非受控组件,这允许编辑器在大型文档上表现良好。

当将编辑器用作非受控组件时,避免使用 value 和 onEditorChange 属性。Tiny 建议在需要时检索编辑器内容。可以使用 onInit 事件处理器在编辑器加载时存储编辑器引用,以帮助检索内容。

为了在内容准备好保存时向用户提供视觉反馈,请使用 onDirty 事件处理器;并结合在保存编辑器内容时清除编辑器的“脏”状态。

当用户在初始化或最后一次 tinymce.editor.save() 调用后修改编辑器内容时,编辑器处于“脏”(或“脏”状态)。这包括使用撤销或重做所做的更改。

示例:带有保存按钮和脏状态的函数式非受控组件

function MyComponent({initialValue}) {
  const editorRef = useRef(null);
  const [dirty, setDirty] = useState(false);
  useEffect(() => setDirty(false), [initialValue]);
  const save = () => {
    if (editorRef.current) {
      const content = editorRef.current.getContent();
      setDirty(false);
      editorRef.current.setDirty(false);
      // an application would save the editor content to the server here
      console.log(content);
    }
  };
  return (
    <>
      <Editor
        initialValue={initialValue}
        onInit={(evt, editor) => editorRef.current = editor}
        onDirty={() => setDirty(true)}
      />
      <button onClick={save} disabled={!dirty}>Save</button>
      {dirty && <p>You have unsaved content!</p>}
    </>
  );
}

将 TinyMCE React 组件作为受控组件使用

受控组件在处理大文档时可能存在性能问题,因为它需要在每次按键或修改时将整个文档转换为字符串。

要将编辑器用作 受控组件,必须同时提供 value 和 onEditorChange 属性。

value 属性用于设置和重置编辑器内容。如果未将其更新为编辑器内容的最新版本,编辑器将回滚任何更改。

onEditorChange 属性用于提供一个事件处理程序,该处理程序将在对编辑器内容进行任何更改时运行。为了防止更改被回滚,编辑器的更改必须在 200 毫秒 内应用到 value 属性。

示例:函数式受控组件

function MyComponent({initialValue}) {
  const [value, setValue] = useState(initialValue ?? '');
  useEffect(() => setValue(initialValue ?? ''), [initialValue]);
  return (
    <Editor
      initialValue={initialValue}
      value={value}
      onEditorChange={(newValue, editor) => setValue(newValue)}
    />
  );
}

示例:类式受控组件

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = { value: props.initialValue ?? '' };
    this.handleEditorChange = this.handleEditorChange.bind(this);
  }

  componentDidUpdate(prevProps) {
    if (this.props.initialValue !== prevProps.initialValue) {
      this.setState({ value: this.props.initialValue ?? '' })
    }
  }

  handleEditorChange(value, editor) {
    this.setState({ value });
  }

  render() {
    return (
      <Editor
        initialValue={this.props.initialValue}
        value={this.state.value}
        onEditorChange={this.handleEditorChange}
      />
    )
  }
}

当必须限制编辑器以避免无效状态(例如超过最大长度)时,必须添加 onBeforeAddUndo 的处理程序,以防止这些状态出现在撤销历史中。

示例:有限长度的受控组件

function MyComponent({initialValue, limit}) {
  const sizeLimit = limit ?? 50;
  const [ value, setValue ] = React.useState(initialValue ?? '');
  const [ length, setLength ] = React.useState(0);

  const handleInit = (evt, editor) => {
    setLength(editor.getContent({ format: 'text' }).length);
  };

  const handleUpdate = (value, editor) => {
    const length = editor.getContent({ format: 'text' }).length;
    if (length <= sizeLimit) {
      setValue(value);
      setLength(length);
    }
  };

  const handleBeforeAddUndo = (evt, editor) => {
    const length = editor.getContent({ format: 'text' }).length;
    // note that this is the opposite test as in handleUpdate
    // because we are determining when to deny adding an undo level
    if (length > sizeLimit) {
      evt.preventDefault();
    }
  };

  return (
    <>
      <Editor
        initialValue={initialValue}
        value={value}
        onInit={handleInit}
        onEditorChange={handleUpdate}
        onBeforeAddUndo={handleBeforeAddUndo}
      />
      <p>Remaining: {sizeLimit - length}</p>
    </>
  );
};

有关 React 中受控组件的信息,请参阅:React 文档 - 受控组件。

事件绑定

可以将函数绑定到编辑器事件,例如:

<Editor onSelectionChange={this.handlerFunction} />

当调用处理程序时(本例中的 handlerFunction),它将带有两个参数被调用:

event

TinyMCE 事件对象。

editor

编辑器的引用。

以下事件可用:

  • onActivate

  • onAddUndo

  • onBeforeAddUndo

  • onBeforeExecCommand

  • onBeforeGetContent

  • onBeforeRenderUI

  • onBeforeSetContent

  • onBeforePaste

  • onBlur

  • onChange

  • onClearUndos

  • onClick

  • onContextMenu

  • onCompositionEnd

  • onCompositionStart

  • onCompositionUpdate

  • onCopy

  • onCut

  • onDblclick

  • onDeactivate

  • onDirty

  • onDrag

  • onDragDrop

  • onDragEnd

  • onDragGesture

  • onDragOver

  • onDrop

  • onExecCommand

  • onFocus

  • onFocusIn

  • onFocusOut

  • onGetContent

  • onHide

  • onInit

  • onInput

  • onKeyDown

  • onKeyPress

  • onKeyUp

  • onLoadContent

  • onMouseDown

  • onMouseEnter

  • onMouseLeave

  • onMouseMove

  • onMouseOut

  • onMouseOver

  • onMouseUp

  • onNodeChange

  • onObjectResizeStart

  • onObjectResized

  • onObjectSelected

  • onPaste

  • onPostProcess

  • onPostRender

  • onPreProcess

  • onProgressState

  • onRedo

  • onRemove

  • onReset

  • onSaveContent

  • onSelectionChange

  • onSetAttrib

  • onSetContent

  • onShow

  • onSubmit

  • onUndo

  • onVisualAid