单实例示例

← 快速开始 | 多实例示例 →

单实例场景使用独立 Subframe:父页面保留工具栏和状态,OnlyOffice Embed SDK 运行在固定的 rat.onlyoffice.* 子域名中。这样即使只有一个编辑器,也不会把 SDK 全局对象、事件总线和文档状态放进宿主页面。

在线演示:站点路由 /docs/demos/single
完整源码src/features/demo/office-preview-page.tsx

在线演示

下方为可交互的单实例编辑器。

单实例

更多
审批批注0 条
审批修订0 条

核心思路

  1. 父页面挂载 rat.onlyoffice.localhost(生产环境为 rat.onlyoffice.agent-bridges.com)的 /subframe iframe
  2. SubframeManager 通过精确 targetOriginpostMessage RPC 请求子框架打开文档
  3. 工具栏调用 openDocument / downloadExport / setReadOnly / setTheme / toggleLanguage / printLogs
  4. 页面卸载时向子框架发送 destroy,再释放父页面管理器

Subframe 组件

"use client";

import { memo } from "react";

const OnlyOfficeSubframeHost = memo(function OnlyOfficeSubframeHost({
  src,
  onLoad,
}: {
  src: string;
  onLoad: () => void;
}) {
  return (
    <iframe
      src={src}
      title="OnlyOffice Embed SDK · 🐀 鼠"
      data-onlyoffice-subframe="true"
      className="absolute inset-0 h-full w-full border-0"
      onLoad={onLoad}
    />
  );
});

初始化与销毁

useEffect(() => {
  const manager = new SubframeManager({
    containerId: "onlyoffice-subframe-editor",
    fileType: FILE_TYPE.DOCX,
    defaultFileName: "New_Document.docx",
    readOnly,
    theme: currentTheme,
    instanceId: "single-editor",
    targetOrigin: getSubframeOrigin("rat"),
    frame: frameRef.current,
  });

  managerRef.current = manager;
  void manager.openDocument({
    fileName: "New_Document.docx",
    isNew: true,
  });

  return () => {
    manager.destroy();
    managerRef.current = null;
  };
}, []);

工具栏操作

const handleOpenDocument = (fileName: string, file?: File) =>
  managerRef.current?.openDocument({ fileName, file, readOnly });

const handleExport = () => managerRef.current?.downloadExport();

const handleToggleReadOnly = async () => {
  const manager = managerRef.current;
  await manager?.setReadOnly(!manager.getReadOnly());
  setReadOnly(managerRef.current?.getReadOnly() ?? false);
};

const handleThemeChange = async (theme: OfficeTheme) => {
  await managerRef.current?.setTheme(theme);
  setCurrentThemeState(managerRef.current?.getTheme() ?? theme);
};

const handleLanguageSwitch = async () => {
  const nextLang = await managerRef.current?.toggleLanguage();
  setCurrentLangState(nextLang);
};

页面结构

export function OfficePreviewPage({ embedded = false, ...props }) {
  return (
    <div className={`flex flex-col bg-white ${embedded ? "h-full min-h-0" : "h-screen"}`}>
      <header>{/* 语言 / 主题 / 上传 / 新建 / 导出 / 只读 */}</header>
      <div className="relative min-h-0 flex-1">
        <OnlyOfficeSubframeHost src={subframeSrc} onLoad={handleFrameLoad} />
        {loading && <LoadingOverlay />}
      </div>
      <input ref={fileInputRef} type="file" className="hidden" onChange={...} />
    </div>
  );
}

支持能力

能力API
上传文件manager.openDocument({ fileName, file })
新建空白manager.openDocument({ fileName: defaultFileName })
导出manager.downloadExport()
只读切换manager.setReadOnly(!manager.getReadOnly())
主题manager.setTheme(theme)
语言manager.toggleLanguage()
打印日志manager.printLogs()