在过去几年中,大多数基于 Microsoft 365 和 SharePoint Online 构建的企业解决方案都利用 SharePoint 功能框架的网站 CustomAction
功能来扩展页面的 UI。 使用 SharePoint 的“新式”UI 时,大多数自定义项不再可用。 使用SharePoint 框架扩展,可以在“新式”UI 中提供类似的功能。
本教程介绍如何将旧版“经典”自定义迁移到当前模型:SharePoint 框架扩展。
首先,介绍一下 SharePoint 框架扩展的开发选项:
- 应用程序自定义工具:通过将自定义 HTML 元素和客户端代码添加到“新式”页面的预定义占位符来扩展 SharePoint 的本地“新式”UI。 有关应用程序自定义工具的详细信息,请参阅生成第一个 SharePoint 框架扩展(Hello World第 1 部分)。
- 命令集:将自定义编辑控制块 (ECB) 菜单项或自定义按钮添加到列表或库的列表视图的命令栏。 可以将任何客户端操作关联到这些命令。 有关命令集的详细信息,请参阅生成第一个 ListView 命令集扩展。
- 字段自定义工具:使用自定义 HTML 元素和客户端代码自定义列表视图中字段的呈现。 有关字段自定义工具的详细信息,请参阅生成第一个字段自定义工具扩展。
在本文中,最有用的选项是命令集扩展。
假设 SharePoint Online 中有 一个 CustomAction
,以便为库中的文档提供自定义 ECB 菜单项。 ECB 菜单项的范围是用于打开自定义页面,同时在目标页面的查询字符串中提供当前选定项的列表 ID 和列表项 ID。
在以下代码片段中,可以看到使用 SharePoint 功能框架定义 的 CustomAction
XML 代码。
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="OpenDetailsPageWithItemReference"
Title="Show Details"
Description="Opens a new page with further details about the currently selected item"
Sequence="1001"
RegistrationType="List"
RegistrationId="101"
Location="EditControlBlock">
<UrlAction Url="ShowDetails.aspx?ID={ItemId}&List={ListId}" />
</CustomAction>
</Elements>
可以看到,功能元素文件定义了一个 类型的 CustomAction
元素,用于在 EditControlBlock
位置 (即 ECB) 任何库中的任何文档 (RegistrationType
是 List
且 RegistrationId
) 101
。
在下图中,可以看到上一自定义操作在库的列表视图中的输出。
请注意,SharePoint 功能框架 ECB 自定义项在“新式”列表中有效。 实际上,只要不使用 JavaScript 代码,列表自定义操作就仍可用于“新式”列表。
若要将上一解决方案迁移到 SharePoint 框架,请参阅以下步骤。
新建 SharePoint 框架解决方案
在控制台中,为项目新建文件夹:
md spfx-ecb-extension
转到项目文件夹:
cd spfx-ecb-extension
通过运行 Yeoman SharePoint 生成器创建新的SharePoint 框架解决方案 Web 部件。
yo @microsoft/sharepoint
出现提示时,请输入以下值(为下面省略的所有提示选择默认选项):
- 解决方案名称是什么?: spfx-ecb-extension
- 你想要为你的组件设定哪些基准包?:仅需要 SharePoint Online(最新)
- 要创建哪种类型的客户端组件?:扩展
- 要创建哪种类型的客户端扩展? 列表视图命令集
- 命令集名称是什么? CustomECB
此时,Yeoman 安装必需的依赖项,并为解决方案文件和文件夹以及“CustomFooter”扩展搭建基架。 这可能需要几分钟的时间才能完成。
启动 Visual Studio Code(或选定代码编辑器),并开始开发解决方案。 若要启动 Visual Studio Code,可以执行下面的语句。
code .
定义新 ECB 项
为了重现使用 SharePoint 功能框架生成的 ECB 菜单项的相同行为,需要在新 SharePoint 框架解决方案中使用客户端代码,从而实现相同的逻辑。 若要完成此任务,请执行以下步骤。
打开文件 ./src/extensions/customEcb/CustomEcbCommandSet.manifest.json。 复制
id
属性的值,并将它存储到安全位置上,因为稍后将需要用到它。在同一文件中,编辑文件下半部分中的 数组
items
,为命令集定义单个命令。 调用命令 ShowDetails,再指定标题和命令类型。 下面的屏幕截图展示了清单文件。{ "$schema": "https://developer.microsoft.com/json-schemas/spfx/command-set-extension-manifest.schema.json", "id": "5d3bac4c-e040-44ed-ab43-464490d22762", "alias": "CustomEcbCommandSet", "componentType": "Extension", "extensionType": "ListViewCommandSet", "version": "*", "manifestVersion": 2, "requiresCustomScript": false, "items": { "ShowDetails": { "title": { "default": "Show Details" }, "type": "command" } } }
打开文件 ./src/extensions/customEcb/CustomEcbCommandSet.ts ,并根据以下代码片段编辑内容:
import { Guid } from '@microsoft/sp-core-library'; import { override } from '@microsoft/decorators'; import { BaseListViewCommandSet, Command, IListViewCommandSetListViewUpdatedParameters, IListViewCommandSetExecuteEventParameters } from '@microsoft/sp-listview-extensibility'; import { Dialog } from '@microsoft/sp-dialog'; import * as strings from 'CustomEcbCommandSetStrings'; export interface ICustomEcbCommandSetProperties { targetUrl: string; } export default class CustomEcbCommandSet extends BaseListViewCommandSet<ICustomEcbCommandSetProperties> { @override public onInit(): Promise<void> { return Promise.resolve(); } @override public onListViewUpdated(event: IListViewCommandSetListViewUpdatedParameters): void { const compareOneCommand: Command = this.tryGetCommand('ShowDetails'); if (compareOneCommand) { // This command should be hidden unless exactly one row is selected. compareOneCommand.visible = event.selectedRows.length === 1; } } @override public onExecute(event: IListViewCommandSetExecuteEventParameters): void { switch (event.itemId) { case 'ShowDetails': const itemId: number = event.selectedRows[0].getValueByName("ID"); const listId: Guid = this.context.pageContext.list.id; window.___location.replace(`${this.properties.targetUrl}?ID=${itemId}&List=${listId}`); break; default: throw new Error('Unknown command'); } } }
请注意文件开头处引用
Guid
类型的import
语句,它用于保留当前列表的 ID。接口
ICustomEcbCommandSetProperties
声明名为targetUrl
的单个属性,该属性可用于在选择 ECB 菜单项时提供要打开的目标页面的 URL。此外,
onExecute()
方法重写可处理自定义操作的执行。 请注意从event
参数中读取当前选定项的 ID,以及从pageContext
对象中读取源列表 ID 的代码片段。最后,请注意
onListViewUpdated()
方法重写。默认情况下,仅当选择的是一个项时,此方法重写才启用ShowDetails
命令。目标 URL 重定向是通过经典 JavaScript 代码和
window.___location.replace()
函数进行处理。 可以在 方法中编写任何你喜欢的onExecute()
TypeScript 代码。 仅出于举例目的,可以利用 SharePoint 框架对话框架打开新的对话框窗口,并与用户进行交互。注意
有关SharePoint 框架对话框框架的详细信息,请参阅将自定义对话框与SharePoint 框架扩展配合使用。
下图展示了所生成的输出。
在调试模式下测试解决方案
返回到控制台窗口,并运行下面的命令,以生成解决方案,并运行本地 Node.js 服务器来托管它。
gulp serve --nobrowser
打开常用浏览器,并转到任意“新式”团队网站的“新式”库。 将以下查询字符串参数追加到 AllItems.aspx 网页 URL 中。
?loadSpfx=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={"6c5b8ee9-43ba-4cdf-a106-04857c8307be":{"___location":"ClientSideExtension.ListViewCommandSet.ContextMenu","properties":{"targetUrl":"ShowDetail.aspx"}}}
在上面的查询字符串中,将 GUID 替换为从 CustomEcbCommandSet.manifest.json 文件中保存的
id
值。此外,还有一个
___location
属性假定 ClientSideExtension.ListViewCommandSet.ContextMenu 的值,该值指示 SPFx 将命令集呈现为 ECB 菜单项。 下面是___location
属性的所有选项:- ClientSideExtension.ListViewCommandSet.ContextMenu:项的上下文菜单 (s) 。
- ClientSideExtension.ListViewCommandSet.CommandBar:列表或库中的顶部命令集菜单。
- ClientSideExtension.ListViewCommandSet:上下文菜单和命令栏 (都对应于
SPUserCustomAction.Location="CommandUI.Ribbon"
) 。
在查询字符串中,仍存在一个名为
properties
的属性,该属性表示类型的ICustomEcbCommandSetProperties
对象的 JSON 序列化,该对象是自定义命令集请求的用于呈现的自定义属性的类型。请注意,出于安全考虑,在执行页面请求时,可能会看到警告消息框(标题为“允许调试脚本?”),提示是否同意通过 localhost 运行代码。 若要在本地调试和测试解决方案,必须通过选择“加载调试脚本”同意这样做。
注意
或者,你可以在项目的 config/serve.json 文件中创建服务配置条目,以自动创建调试查询字符串参数,如以下文档中所述:在新式 SharePoint 页面上调试 SharePoint 框架解决方案
打包和托管解决方案
如果对结果感到满意,就可以准备打包解决方案,并将它托管在实际宿主基础结构中。
生成捆绑包和程序包前,需要声明 XML 功能框架文件来预配扩展。
查看功能框架元素
在代码编辑器中,打开解决方案文件夹的 /sharepoint/assets 子文件夹并编辑 elements.xml 文件。 应按照下面的代码片段编辑此文件。
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Title="CustomEcb" RegistrationId="101" RegistrationType="List" Location="ClientSideExtension.ListViewCommandSet.ContextMenu" ClientSideComponentId="6c5b8ee9-43ba-4cdf-a106-04857c8307be" ClientSideComponentProperties="{"targetUrl":"ShowDetails.aspx"}"> </CustomAction> </Elements>
可以看到,它类似于“经典”模型中的 SharePoint 功能框架文件,不同之处在于它使用
ClientSideComponentId
属性引用自定义扩展的id
,并引用ClientSideComponentProperties
属性来配置扩展所需的自定义配置属性。在解决方案中打开文件 ./config/package-solution.json 。 在 文件中,可以看到节中有
assets
对 elements.xml 文件的引用。{ "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json", "solution": { "name": "spfx-ecb-extension-client-side-solution", "id": "b8ff6fdf-16e9-4434-9fdb-eac6c5f948ee", "version": "1.0.2.0", "features": [ { "title": "Custom ECB Menu Item.", "description": "Deploys a custom ECB menu item sample extension", "id": "f30a744c-6f30-4ccc-a428-125a290b5233", "version": "1.0.0.0", "assets": { "elementManifests": [ "elements.xml" ] } } ] }, "paths": { "zippedPackage": "solution/spfx-ecb-extension.sppkg" } }
捆绑、打包和部署SharePoint 框架组件
为 SharePoint Online 租户准备和部署解决方案:
执行下列任务,以捆绑解决方案。 这将创建项目的发布版本:
gulp bundle --ship
执行下列任务来打包解决方案。 此命令在 sharepoint/solution 文件夹中创建 *.sppkg 包。
gulp package-solution --ship
将新建的客户端解决方案包上传或拖放到租户上的应用程序目录中,再选择“部署”按钮。
安装并运行解决方案
打开浏览器,并转到任意目标“新式”网站。
转到“网站内容”页,并选择添加新“应用”。
在“来自组织的应用”中,选择安装新应用,以浏览应用程序目录中的解决方案。
选择“spfx-ecb-extension-client-side-solution”解决方案,并在目标网站上安装它。
应用安装完成后,打开网站的“文档”库,再选择一个文档来查看自定义 ECB 菜单项的实际效果。
享受使用SharePoint 框架扩展构建的新自定义 ECB 菜单项!