You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React开发SPO客户端WebPart调用OfficeJs报‘Office未定义’求助

解决SharePoint WebPart中“Office is not defined”错误及Outlook调用问题

一、核心问题分析

  • Office.js加载时机错误:在React组件render方法中插入<script>标签,无法保证脚本在componentDidMount或按钮点击前加载完成,导致Office对象未定义。
  • 宿主环境误解:Outlook Add-In运行在Outlook宿主中,拥有Office.context.mailbox上下文,但SharePoint WebPart的宿主是SharePoint/浏览器,原生不支持mailbox相关API,这是后续调用失败的根本原因。
  • 类型配置冗余:tsconfig.json中同时引入office-js和@types/office-js类型,可能导致冲突。

二、修复“Office is not defined”错误

1. 全局加载Office.js

修改WebPart的onInit方法,在WebPart初始化阶段动态加载Office.js,确保脚本在组件渲染前完成加载:

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import ReplyEmailComponent from './components/ReplyEmailComponent';

export default class ReplyEmailWebPart extends BaseClientSideWebPart<unknown> {
  private officeLoaded: Promise<void>;

  protected onInit(): Promise<void> {
    this.officeLoaded = new Promise((resolve) => {
      // 检查Office是否已全局加载
      if (window.Office) {
        Office.initialize = () => resolve();
        return;
      }
      // 动态创建script标签加载Office.js
      const script = document.createElement('script');
      script.src = 'https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js';
      script.onload = () => {
        Office.initialize = () => {
          console.log('Office.js初始化完成');
          resolve();
        };
      };
      script.onerror = () => {
        console.error('Office.js加载失败');
        resolve();
      };
      document.head.appendChild(script);
    });

    return Promise.all([super.onInit(), this.officeLoaded]);
  }

  public render(): void {
    const element: React.ReactElement<unknown> = React.createElement(
      ReplyEmailComponent,
      { officeLoaded: this.officeLoaded }
    );

    ReactDom.render(element, this.domElement);
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }
}

2. 调整React组件逻辑

移除组件内的script标签,等待Office.js加载完成后再启用按钮,并替换Outlook专属API为SharePoint环境可用的方案:

import * as React from 'react';

/* global Office */

interface IReplyEmailComponentProps {
  officeLoaded: Promise<void>;
}

export default class ReplyEmailComponent extends React.Component<IReplyEmailComponentProps, { isOfficeReady: boolean }> {
  constructor(props: IReplyEmailComponentProps) {
    super(props);
    this.state = { isOfficeReady: false };
  }

  public async componentDidMount(): Promise<void> {
    try {
      await this.props.officeLoaded;
      this.setState({ isOfficeReady: true });
    } catch (err) {
      console.error('Office.js未加载成功', err);
    }
  }

  private handleClick = (): void => {
    // SharePoint环境下无法使用Outlook Add-In的mailbox API,改用mailto协议唤起本地Outlook
    window.location.href = 'mailto:recipient@example.com?subject=Test email&body=Hello, world!';
  };

  public render(): React.ReactElement<IReplyEmailComponentProps> {
    return (
      <section>
        <div>
          <button 
            onClick={this.handleClick} 
            disabled={!this.state.isOfficeReady}
          >
            {this.state.isOfficeReady ? '发送邮件' : '加载中...'}
          </button>
        </div>
      </section>
    );
  }
}

3. 清理类型配置

修改tsconfig.json,移除冗余的类型引用,避免冲突:

{
  "extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
  "compilerOptions": {
    "target": "es5",
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "jsx": "react",
    "declaration": true,
    "sourceMap": true,
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "outDir": "lib",
    "inlineSources": false,
    "strictNullChecks": false,
    "noUnusedLocals": false,
    "noImplicitAny": true,

    "typeRoots": [
      "./node_modules/@types",
      "./node_modules/@microsoft"
    ],
    "types": [
      "webpack-env",
      "@types/office-js"
    ],
    "lib": [
      "es5",
      "dom",
      "es2015.collection",
      "es2015.promise"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ]
}

4. 清理冗余依赖(可选)

若不需要本地Office.js包,可执行以下命令移除:

npm uninstall @microsoft/office-js

三、关键说明

Office.context.mailbox.displayNewMessageForm是Outlook Add-In专属API,仅能在Outlook宿主环境中运行。在SharePoint WebPart中,唤起本地Outlook新建邮件最可靠的方式是使用mailto:协议链接;若需要更复杂的邮件操作(如添加附件、HTML格式),可考虑使用Microsoft Graph API(需用户授权)。

内容的提问来源于stack exchange,提问作者EduardoCMB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:55:00