有关使用 Power Apps 组件框架创建的代码组件的最佳做法和指南

使用这些Power Apps组件框架最佳做法来开发、部署和维护具有更好的可用性、可支持性和性能的代码组件。 本指南涵盖以下方面:

  • Power Apps 组件框架
  • Microsoft Power Apps
  • TypeScript 和 JavaScript
  • HTML 浏览器用户界面开发
  • Azure DevOps/GitHub

本文概述了开发代码组件的专业人员的既定最佳做法和指南。 本文旨在介绍每个组件背后的优势,以便代码组件可以利用这些工具和提示提供的可用性、可支持性和性能改进。

Power Apps 组件框架

本部分包含与Power Apps组件框架本身相关的最佳做法和指南。

避免将开发版本部署到 Dataverse

生产或开发模式下生成代码组件。 避免将开发版本部署到 Dataverse,因为它们会对性能产生不利影响,甚至可能由于部署大小而被阻止部署。 即使计划以后部署发布版本,如果还没有自动化发布管道,也很容易忘记重新部署。 有关详细信息,请参阅 调试自定义控件

避免使用不受支持的框架方法

不要使用 ComponentFramework.Context 上未公开的内部方法。 这些方法可能有效,但由于它们不受支持,因此它们可能会在将来的版本中停止工作。 不支持使用访问主机应用程序 HTML 文档对象模型(DOM)的控制脚本。 主机应用程序 DOM 位于代码组件边界之外的任何部分都可能会更改,但不会通知。

使用 init 方法请求网络所需的资源

当宿主上下文加载代码组件时,它首先调用 init 方法。 使用此方法可请求任意网络资源(例如元数据),而无需等待 updateView 方法。 updateView如果在请求返回之前调用该方法,则代码组件必须处理此状态并提供视觉加载指示器。

清理 destroy 方法内部的资源

当从浏览器 DOM 中删除代码组件时,宿主上下文将调用 destroy 方法。 使用 destroy 方法来关闭在容器元素外部添加的任何 WebSockets,并移除在容器元素外部添加的事件处理程序。 如果您使用 React,请在 destroy 方法内部使用 ReactDOM.unmountComponentAtNode。 以这种方式清理资源可防止代码组件在给定浏览器会话中加载和卸载导致的性能问题。

避免对数据集属性进行不必要的刷新调用

如果代码组件的类型为数据集,绑定数据集属性会公开一种 refresh 导致宿主上下文重新加载数据的方法。 调用此方法会不必要地影响代码组件的性能。

尽量减少对 notifyOutputChanged 的调用

在某些情况下,不建议 UI 控件的更新(例如按键或鼠标移动事件)每次都调用 notifyOutputChanged,因为对 notifyOutputChanged 的更多调用会导致向父上下文传播的事件数量远超实际需求。 相反,请考虑改为在控件失去焦点时,或在用户完成触摸或鼠标操作时触发事件。

检查 API 可用性

为不同的主机(模型驱动应用、画布应用、门户)开发代码组件时,请始终检查在这些平台上用于支持的 API 的可用性。 例如, context.webAPI 画布应用中不可用。 有关单个 API 可用性,请参阅Power Apps组件框架 API 参考

管理传递到 的值为 null 的临时属性值

当数据尚未准备好时,空值会被传递给 updateView 方法。 组件应考虑到这种情况,并预期数据可能为 null,且在后续的 updateView 周期中可能会包含更新后的值。 updateView 适用于 标准 组件和 React 组件。

模型驱动应用

本部分包含与模型驱动应用中的代码组件相关的最佳做法和指南。

请勿直接与 formContext 交互

如果你有使用客户端 API 的经验,可能已经习惯于通过 formContext 进行交互,以访问属性、控件并调用 API 方法,例如 saverefreshsetNotification。 代码组件需要在各种产品中运行,例如模型驱动应用、画布应用和仪表板,因此不能依赖 formContext

解决方法是使代码组件绑定到列,并将事件处理程序添加到 OnChange 该列。 代码组件可以更新列值,OnChange事件处理程序可以访问formContext。 将来将添加对自定义事件的支持,这样就可以在不添加列配置的情况下在控件外部进行通信更改。

限制对 WebApi 的调用规模和频率

使用 context.WebApi 方法时,请限制调用数和数据量。 每次调用 WebApi 都会计入用户的 API 配额和服务保护限制。 对记录执行 CRUD 操作时,请考虑有效负载的大小。 通常,请求有效负载越大,代码组件的速度就越慢。

画布应用

本部分包含与画布应用中的代码组件相关的最佳做法和指南。

最小化屏幕上的组件数

每次向画布应用中添加组件时,渲染都需要一定的时间。 呈现时间随添加的每个组件一起增加。 使用开发人员性能工具将更多内容添加到屏幕时,请仔细测量代码组件的性能。

目前,每个代码组件捆绑自己的共享库,例如 Fluent UI 和 React。 加载同一库的多个实例不会多次加载这些库。 但是,加载多个不同的代码组件会导致浏览器加载这些库的多个捆绑版本。 将来,可以使用代码组件加载和共享这些库。

允许创建者设置代码组件的样式

当应用创建者从画布应用内部使用代码组件时,他们希望使用与应用其余部分匹配的样式。 使用输入属性为主题元素(如颜色和大小)提供自定义选项。 使用 Microsoft Fluent UI 时,将这些属性映射到库提供的主题元素。 将来,主题支持将添加到代码组件,以便简化此过程。

遵循画布应用的性能最佳实践

画布应用通过应用内部和解决方案检查器提供了丰富的最佳实践。 在添加代码组件之前,请确保应用遵循这些建议。 有关详细信息,请参见:

TypeScript 和 JavaScript

本部分包含与代码组件中的 TypeScript 和 JavaScript 相关的最佳做法和指南。

ES5 与 ES6

默认情况下,代码组件面向 ES5 以支持较旧的浏览器。 如果不想支持这些较旧的浏览器,请将目标更改为文件夹内的 pcfprojtsconfig.jsonES6。 有关详细信息,请参阅 ES5 与 ES6

模块导入

始终打包代码组件所需的模块,而不要使用那些需要通过 SCRIPT 标签加载的脚本。 例如,如果要使用非 Microsoft 图表 API,而示例中显示需要将 <script type="text/javascript" src="somechartlibrary.js></script> 添加到页面,则这种方法在代码组件内不受支持。 捆绑所有必需的模块将代码组件与其他库隔离开来,还支持在脱机模式下运行。

注释

尚不支持通过在组件清单中使用库节点来实现组件之间共享库。

为代码组件配置 ESLint

Linting 是指使用工具扫描代码以查找潜在问题。 pac pcf init 使用的模板将eslint模块安装到项目,并通过添加.eslintrc.json文件对其进行配置。 Eslint 需要配置 TypeScript 和 React 编码样式。 它还可以在可能的情况下自动修复其中一些问题。 若要配置,请使用以下命令:

npx eslint --init

然后在出现提示时回答以下问题:

  • 你想如何使用ESLint? 答: 检查语法、查找问题并强制实施代码样式

  • 项目使用的模块类型是什么? 答: JavaScript 模块(导入/导出)

  • 项目使用哪种框架? 答: React

  • 项目是否使用 TypeScript? 答:

  • 代码在何处运行? 答: 浏览器

  • 你希望如何定义项目的样式? 答案:回答有关您的风格的问题

  • 你希望配置文件采用哪种格式? 答: JSON (此答案更新现有 .eslintrc.json

  • 您使用哪种缩进风格? 答:空格(此缩进样式为Visual Studio Code默认值)

  • 您为字符串使用哪种引号? 答案:单选

  • 你使用什么行尾符? 答:Windows(此行尾是Visual Studio Code默认 CRLF 行尾样式。

  • 是否需要分号? 答:

注释

可以自定义此配置以满足你的特定需求(例如,如果不使用 React)。 有关详细信息,请参阅 ESLint 入门

在使用 eslint之前,需要将一些脚本添加到 package.json

 "scripts": {
    ...
    "lint": "eslint MY_CONTROL_NAME --ext .ts,.tsx",
    "lint:fix": "npm run lint -- --fix"
  }

eslint 脚本接受包含代码的文件夹。 将 MY_CONTROL_NAME 替换为调用 pac pcf init 时使用的代码组件的名称。

现在,在命令行中,可以使用:

npm run lint:fix

此命令将更改项目中的代码以匹配所选样式,并且还会报告稍后解决的一些问题。

注释

ESLint 起初会指出模板代码中的问题(例如空构造函数)。 可以添加内联注释以指示 ESLint 排除规则,例如: // eslint-disable-next-line @typescript-eslint/no-empty-function

此外,还可以通过将以下内容添加到 .eslintrc.json 中来添加要忽略的文件(例如自动生成的接口):

"ignorePatterns": ["**/generated/*.ts"]

有关详细信息,请参阅 配置文件中的 ignorePatterns

Tip

你可以安装一个 Visual Studio Code 扩展,该扩展使用项目的 .eslintrc.json 文件对检测到的任何问题提供代码高亮显示,并可选择直接在 IDE 中修复这些问题。 有关详细信息,请参阅Visual Studio Code中的管理扩展

HTML 浏览器用户界面开发

本部分包含 HTML 浏览器 UI 开发的最佳做法和指南。

使用 Microsoft Fluent UI React

Fluent UI React 是官方开放源代码 React 前端框架,旨在构建无缝融入各种Microsoft产品的体验。 Power Apps本身使用 Fluent UI,因此可以创建与其余应用一致的 UI。

使用基于路径的 Fluent 导入来减小捆绑包大小

目前,与 pac pcf init 一起使用的代码组件模板不支持树摇动。 树摇动是指 webpack 检测到您导入但未使用的模块并将其移除的过程。 如果使用以下命令从 Fluent UI 导入,则导入并捆绑整个库:

import { Button } from '@fluentui/react'

若要避免导入和捆绑整个库,请使用基于路径的导入,其中使用显式路径导入特定库组件:

import { Button } from '@fluentui/react/lib/Button';

使用特定路径可减少开发和发布版本中的捆绑包大小。

您可以通过更新 tsconfig.json,在 compilerOptions 部分中使用以下模块配置,从而利用树摇技术(该技术仅影响发布和生产构建):

"module": "es2015",
"moduleResolution": "node"

详细信息: Fluent UI - 高级用法

优化 React 渲染

使用 React 时,请遵循特定于 React 的最佳做法来最大程度地减少组件的呈现。 此方法会导致响应更迅速的 UI。 以下列表包括一些最佳做法:

  • 仅当绑定属性或框架层面的更改需要 UI 反映这些变化时,才在 ReactDOM.render 方法中调用 updateView。 使用 updatedProperties 确定更改的内容。
  • 尽可能使用 PureComponent (包含类组件)或 React.memo (具有函数组件),以避免在组件输入属性不更改时不必要的重新呈现组件。
  • 对于大型 React 组件,将 UI 分解为较小的组件以提高性能。
  • 避免在呈现函数中使用箭头函数和函数绑定。 这些做法会在每次渲染时创建一个新的回调闭包,并导致每当父组件渲染时,子组件都会重新渲染。 请改为在构造函数中绑定函数,或使用类字段箭头函数。 请参阅 处理事件 - React

检查无障碍功能

确保可访问代码组件,以便仅键盘和屏幕阅读器用户可以使用它们:

  • 为鼠标和触摸操作提供键盘导航替代方式。 例如,如果组件提供下拉列表,请确保用户可以使用 Tab 设置焦点,然后使用箭头键导航选项。
  • 确保 alt 的 ARIA(可访问的富互联网应用程序)属性已正确设置,以便屏幕阅读器能准确朗读代码组件界面的内容。 Microsoft Fluent UI 库使使用这些属性变得简单,因为许多组件已经可访问且屏幕阅读器兼容。
  • 现代浏览器开发者工具提供了多种实用方式来检查无障碍功能。 使用这些工具检查代码组件中的常见无障碍问题。

有关详细信息,请参阅在 Power Apps 中创建可访问的画布应用

始终使用异步网络调用

进行网络调用时,切勿使用同步阻止请求,因为此请求会导致应用停止响应并导致性能缓慢。 有关详细信息,请参阅 异步与 HTTP 和 HTTPS 资源交互

为多个浏览器写入代码

模型驱动应用、画布应用和门户都支持多个浏览器。 请务必仅使用所有新式浏览器支持的技术,并使用一组具有代表性的浏览器进行测试,供目标受众使用。

代码组件应计划支持多个客户端和屏幕格式

可以在多个客户端(模型驱动应用、画布应用、门户)和屏幕格式(移动、平板电脑、Web)中呈现代码组件。 在模型驱动应用中使用时,数据集代码组件可以放置在主窗体网格、相关记录网格、子网格或仪表板上。 在画布应用中使用时,代码组件可以放置在响应式容器中,这些容器使用应用创建者提供的配置动态调整大小。

  • 通过使用 trackContainerResize,代码组件可以响应可用宽度和高度的变化。 在某些情况下,设置此属性将呈现适合可用空间的不同 UI。 可以合并 allocatedHeightallocatedWidth 结合 getFormFactor 以确定代码组件是否在移动、平板电脑或 Web 客户端上运行。 有关详细信息,请参阅此 选项选取器教程
  • 通过实现 setFullScreen,用户可以展开以使用空间受限的整个可用屏幕。 有关详细信息,请参阅 Canvas 应用网格组件
  • 如果代码组件无法在给定容器大小中提供有意义的体验,则应适当禁用功能并向用户提供反馈。

始终使用作用域化的 CSS 规则

使用 CSS 为代码组件设置样式时,请确保将 CSS 的作用范围限制在该组件内。 使用应用于容器 DIV 元素的自动生成 CSS 类,用于您的组件。 如果将 CSS 作用域设置为全局,可能会破坏渲染代码组件的表单或页面的现有样式。 如果使用第三方 CSS 框架,请使用该框架的命名空间版本,或者手动或通过使用 CSS 预处理器将框架包装在命名空间中。

例如,如果命名空间为 SampleNamespace 代码组件名称 LinearInputComponent,请使用以下代码添加自定义 CSS 规则:

.SampleNamespace\.LinearInputComponent rule-name

避免使用 Web 存储对象

代码组件不应使用 HTML Web 存储对象(例如 window.localStoragewindow.sessionStorage)来存储数据。 存储在用户浏览器或移动客户端本地的数据不安全,不能保证可靠可用。

ALM、Azure DevOps 和GitHub

有关使用 ALM、Azure DevOps 和 GitHub 的代码组件的最佳做法,请参阅有关 Code 组件应用程序生命周期管理(ALM)的文章。