自适应卡片扩展 (ACE) 是一种新的SharePoint 框架组件类型,使开发人员能够生成丰富的本机扩展来Viva Connections的仪表板和 SharePoint 页面。 由于自适应卡片扩展使用 Microsoft 的自适应卡片框架通过其声明性 JSON 架构生成 UI,因此只需专注于组件的业务逻辑,并让 SharePoint 框架 (SPFx) 处理使组件看起来良好,并在所有平台上工作。
本教程假设你已安装 SPFx v1.13。 有关安装 v1.13 SPFx 的详细信息,请参阅
SharePoint 框架 v1.13 发行说明
。
搭建自适应卡片扩展项目
为项目创建新的项目目录,将当前文件夹更改为该目录。
通过从你创建的新目录中运行 Yeoman SharePoint 生成器来创建新项目:
yo @microsoft/sharepoint
出现提示时,请输入以下值(为下面省略的所有提示选择默认选项):
是否允许租户管理员选择立即将解决方案部署到所有站点,而无需在站点中运行任何功能部署或添加应用? 是
要创建哪种类型的客户端组件? 自适应卡扩展
要使用哪个模板? 主文本模板
自适应卡片扩展名是什么? HelloWorld
自适应卡片扩展说明是什么? Hello World 说明
此时,Yeoman 安装必需的依赖项,并为解决方案文件搭建基架。 此过程可能需要几分钟时间。
更新项目的托管工作台 URL
使用 gulp 任务 服务时,默认情况下,它将启动具有项目中指定的专用托管工作台 URL 的浏览器。 新项目中托管工作台的默认 URL 指向无效的 URL。
找到并打开项目中的文件./config/serve.json。
找到属性 initialPage
:
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx"
将 enter-your-SharePoint-site
域更改为要用于测试 SharePoint 租户和网站的 URL。 例如:https://contoso.sharepoint.com/sites/devsite/_layouts/workbench.aspx
。
还可以通过将 nobrowser
参数包含到 gulp serve 命令来启动本地 Web 服务器,而无需启动浏览器。 例如,你可能不希望修改所有项目中的 serve.json 文件,而是使用书签启动托管工作台。
gulp serve --nobrowser
在 workbench 中为 ACE 提供服务
在深入了解代码之前,请先运行基架输出并查看自适应卡片扩展的外观。
AES 的内部开发循环类似于 SPFx Web 部件。 我们可以在本地提供服务,并在 workbench 上运行代码。
gulp serve
一旦本地 Webserver 运行,则导航到托管的Workbench: https://{tenant}.sharepoint.com/_layouts/15/workbench.aspx
打开 Web 部件工具箱并选择 ACE:
浏览卡片视图
AES 可以采用两种不同的方式呈现。 ACE 呈现的第一种方法称为 卡视图。
在仪表板或页面上呈现时,AES 将始终在此视图中启动。
浏览快速视图
ACE 可以呈现的第二种方法称为 快速视图。 与 ACE 交互时,ACE 可以启动更大的自定义体验。
在 编辑 模式下禁用 ACE 交互。 Workbench 或 Page 必须处于 “预览” 或 “读取” 模式才能与 ACE 交互。
将 Workbench 切换到 “预览” 模式。
选择 ACE 上的 快速视图 按钮:
检查基架代码
在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts。
export default class HelloWorldAdaptiveCardExtension
extends BaseAdaptiveCardExtension<IHelloWorldAdaptiveCardExtensionProps,IHelloWorldAdaptiveCardExtensionState> {
// ...
所有 AES 必须从 BaseAdaptiveCardExtension
类扩展。 可以选择实现两个泛型:
TProperties: 与Web 部件类似,这是组件的持久化属性集 (属性包)。
TState: AES 是独一无二的, 可选地 定义可呈现数据集。
呈现 ACE
protected renderCard(): string | undefined {
return CARD_VIEW_REGISTRY_ID;
renderCard()
方法virtual
返回字符串标识符到已注册视图; 稍后有更多查看注册的信息。 在卡片视图的 初始 呈现期间调用此方法。
如果未重写 renderCard()
,则将呈现默认“卡片视图”。
注释掉 renderCard()
方法,看看会发生什么情况:
protected renderCard(): string | undefined {
return CARD_VIEW_REGISTRY_ID;
取消对 renderCard()
方法的注释,以返回到原始状态。
默认卡片视图将使用清单中的以下属性呈现:
图标: iconProperty
标题:title
卡片文本: description
与卡片视图不同,没有默认的快速视图。
注册 ACE 视图
若要使用视图,必须将其注册到各自的 ViewNavigator。 在 ACE 上公开了两个 ViewNavigator:cardNavigator
和 quickViewNavigator
:
this.cardNavigator.register(CARD_VIEW_REGISTRY_ID, () => new CardView());
this.quickViewNavigator.register(QUICK_VIEW_REGISTRY_ID, () => new QuickView());
必须在使用视图之前注册它。 可以在类的构造函数或 onInit()
方法中执行此操作。
“卡片视图”
定位并打开文件: ./src/adaptiveCardExtensions/helloWorld/cardView/CardView.ts。
卡片视图必须从这些基类中扩展:
BaseBasicCardView
BaseImageCardView
BasePrimaryTextCardView
此外,视图和 ACE 之间共享的 properties
和 state
对象有两个泛型。
TProperties: 视图的属性接口,与 ACE 的持久性属性 (属性包) 使用的相同接口。
TState: AES 是独一无二的, 可选地 定义可呈现数据集。
SPFx 会自动将 ACE 的状态变化传播到每个视图。
data
getter 是唯一必须由“卡片”视图实现的方法。 返回类型对于“视图”的父类是唯一的。
cardButtons
属性确定卡片上显示的按钮数以及单击后需要执行的操作。
如果未实现 cardButtons
,则卡片上不会显示任何按钮。
初始卡视图是在 ACE 的 renderCard()
方法中指定,而初始的“快速视图”则作为按钮操作 parameters
的一部分指定。 这允许两个按钮有可能打开不同的视图。
通过在 cardButtons()
方法返回的数组中添加另一个对象来添加第二个按钮:
public get cardButtons(): [ICardButton] | [ICardButton, ICardButton] | undefined {
return [
title: strings.QuickViewButton,
action: {
type: 'QuickView',
parameters: {
view: QUICK_VIEW_REGISTRY_ID
title: 'Bing',
action: {
type: 'ExternalLink',
parameters: {
target: 'https://www.bing.com'
最初,“卡片”中不会有任何更改。 这是因为 BasePrimaryTextCardView 的 “中等 卡片”大小仅显示一个按钮。 SPFx 将选择元组中的第一个元素。
通过转到“属性窗格”并选择 “大型” 来更改“卡片”大小。
onCardSelection()
方法确定如果单击卡片会发生什么情况。 如果未实现 onCardSelection()
方法,则单击卡片时将不会发生任何情况。
通过修改 onCardSelection()
方法,更改卡片选择以打开 “快速” 视图:
public get onCardSelection(): IQuickViewCardAction | IExternalLinkCardAction | undefined {
return {
type: 'QuickView',
parameters: {
view: QUICK_VIEW_REGISTRY_ID
现在,当你选择该卡片时,它将打开快速视图。
ACE 快速视图
定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/quickView/QuickView.ts。
快速视图必须扩展 BaseAdaptiveCardView 基类。 可以定义三个可选泛型:
TData: 从 data()
getter 方法返回的类型。
TProperties: 与卡片视图类似,这是 ACE 的持久性属性使用的相同接口(属性包)。
TState 与卡片视图类似,这是视图需要呈现的有状态的数据集。 TState 必须与 ACE 的状态接口共享属性。
与“卡片”视图相比,“快速视图”对“自适应卡片”模板架构有更多控制。 template()
getter 必须返回有效的自适应卡模板 JSON。 SPFx ATE 支持自适应卡模板化。 从 data
getter 返回的对象上的属性将自动映射到绑定的模板槽。
例如,${description}
绑定到 this.properties.description
。
// QuickView.ts
public get data(): IQuickViewData {
return {
// ...
description: this.properties.description
// QuickViewTemplate.json.ts
"type": "TextBlock",
"text": "${description}",
"wrap": true
必须使用自适应卡绑定语法,该语法使用 $
和 {}
括号。
让我们更改这一点:
从“快速视图”数据中删除 description
属性,并添加两个按钮。
更新 IQuickViewData
接口,如以下代码所示:
export interface IQuickViewData {
title: string;
subTitle: string;
更新 data()
方法,如以下代码所示:
public get data(): IQuickViewData {
return {
subTitle: this.state.subTitle,
title: strings.Title
定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts。
按如下所示更新 IHelloWorldAdaptiveCardExtensionState
接口和 onInit()
方法:
export interface IHelloWorldAdaptiveCardExtensionState {
subTitle: string;
public onInit(): Promise<void> {
this.state = {
subTitle: 'No button clicked'
// ...
接下来,从“卡片”视图中删除对 this.properties.description
的引用:
定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/cardView/CardView.ts。
删除返回的对象中的 description
属性:
public get data(): IPrimaryTextCardParameters {
return {
primaryText: strings.PrimaryText
在其 template()
getter 中,生成的 ACE “快速”视图从 JSON 文件中返回对象。 现在我们来修改该模板:
定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/quickView/template/QuickViewTemplate.json。
使用以下 JSON 替换此文件的内容:
"schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.2",
"body": [
"type": "TextBlock",
"weight": "Bolder",
"text": "${title}"
"type": "TextBlock",
"text": "${subTitle}",
"wrap": true
"type": "ActionSet",
"actions": [
"type": "Action.Submit",
"title": "Button One",
"style": "positive",
"data": {
"id": "button1",
"message": "Clicked Button One"
"type": "Action.Submit",
"title": "Button Two",
"data": {
"id": "button2",
"message": "Clicked Button Two"
通过刷新浏览器中的托管工作台来测试更改。 如果 gulp serve 仍在运行,则应该会显示已应用于项目的更改:
有关自适应卡片的详细信息,请参阅 https://adaptivecards.io。 此网站还包括自适应卡片设计器,可让你在创建自适应卡片时预览这些卡片的呈现和结构。
此时,你已修改 ACE 以在快速视图卡片中包括两个新按钮。 下一步是实现选择这些按钮时发生的情况。 这将使用 操作处理程序完成。
操作处理程序
操作由所定义的视图处理。
快速视图有两个按钮,但该视图当前未处理 提交 操作。 每当执行“自适应卡片操作”时 (例如在启动 Action.Submit 操作时),就会调用 onAction()
方法。
定位并打开文件 QuickView.ts,并重写 onAction()
以处理两个按钮的选择,如以下代码所示:
import { ISPFxAdaptiveCard, BaseAdaptiveCardView, IActionArguments } from '@microsoft/sp-adaptive-card-extension-base';
public onAction(action: IActionArguments): void {
if (action.type === 'Submit') {
const { id, message } = action.data;
switch (id) {
case 'button1':
case 'button2':
this.setState({
subTitle: message
break;
通过刷新浏览器中的托管工作台来测试更改。 如果 gulp serve 仍在运行,则应该会显示已应用于项目的更改。
选择任一按钮现在都会将状态的 subTitle
设置为 data.message
值,从而导致重新呈现 (稍后会有更多相关内容)。 快速视图的自适应卡片现在将显示此消息,因为它的模板绑定到 subTitle
。
与 Web 部件类似,ACE 可以具有由具有适当权限的用户设置的可配置属性。 这些可以让你自定义 ACE 的每个实现。 这将使用属性窗格完成。
可以像配置 Web 部件一样配置 ACE。 对于 HelloWorldAdaptiveCardExtension.ts 文件中找到的以下方法,API 签名是相同的:
getPropertyPaneConfiguration()
onPropertyPaneFieldChanged()
ACE 的默认基架使用新的 API,其旨在在组件未处于 “编辑” 模式时最大程度地减小捆绑包大小。 loadPropertyPaneResources()
方法利用 Webpack 的分块功能将“属性面板”的特定代码分离到自己的 JS 文件中,然后可以根据需要加载。
除了返回属性窗格配置之外, HelloWorldPropertyPane 类还用于封装所有 “编辑” 模式逻辑。
除“卡片大小”字段外,基架 ACE 还有三个 (3 个) 可配置字段,这些字段在 getPropertyPaneConfiguration()
IHelloWorldAdaptiveCardExtension 接口中定义的方法&中定义:
title
iconProperty
description
卡片视图设计为自动适用于所有卡片尺寸。 除了指定默认卡大小之外,AES 无法控制此属性。
ACE 文件中定义的 title
和 iconProperty
属性(即: HelloWorldAdaptiveCardExtension.ts)分别用于 ACE 的 title()
和 iconProperty()
getter 来配置卡片的标题和图标:
title
值用于“属性窗格”的标题和“卡片”上显示的标题中。
public get title(): string {
return this.properties.title;
iconProperty
值是卡片视图使用的图标的 URL。
protected get iconProperty(): string {
return this.properties.iconProperty || require('./assets/sharepointlogo.png');
state
属性必须在调用 setState()
方法之前进行初始化,并且仅能初始化一次。
public onInit(): Promise<void> {
this.state = {
subTitle: 'No button clicked'
// ...
与 properties
不同,state
不会保留在当前会话中,仅能应用于临时“视图”状态。
基架 ACE 维护 state
对象中的一个 description
属性。 这已过时,因为 ACE 及其所有视图可以直接引用 properties
中存储的 description
。
正在重新渲染
在更新 PropertyPane 中属性或调用 setState()
时,将发生重新呈现。
更新属性窗格的“说明字段”值时,它将更新卡片上的说明。 让我们看一下如何这样做:
定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts。
作为一个简单的示例,请在 onPropertyPaneFieldChanged
事件期间 description
更新时更新 subTitle
值。 将以下代码添加到 ACE HelloWorldAdaptiveCardExtension 类:
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
if (propertyPath === 'description') {
this.setState({
subTitle: newValue
将 Partial<TState>
对象传递给 setState()
方法将使用新值更新所有 Views。 现在,更新属性窗格中的“说明字段”将更新“快速视图”上显示的 subTitle
。
如果未传递任何值或相同的值,则仍会出现重新呈现。
setState()
方法不仅限于“属性窗格”。 它可以在接收到新数据时使用,也可以作为某些用户操作的结果。
本教程结束后,应熟悉以下内容:
搭建“自适应卡扩展”的基架
正在注册视图
更改卡片视图和快速视图
基本操作处理
正在更改用属性窗格
延迟加载属性窗格
如何使用 state
properties
和 state
之间的区别