1# 开发基于JS UI的卡片 2 3 4以下内容介绍基于类Web范式的JS UI卡片开发指南。 5 6 7## 运作机制 8 9卡片框架的运作机制如图1所示。 10 11**图1** 卡片框架运作机制(Stage模型) 12 13 14 15卡片使用方包含以下模块: 16 17- 卡片使用:包含卡片的创建、删除、请求更新等操作。 18 19- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的相关操作到卡片管理服务。 20 21卡片管理服务包含以下模块: 22 23- 周期性刷新:在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新。 24 25- 卡片缓存管理:在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延。 26 27- 卡片生命周期管理:对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理。 28 29- 卡片使用方对象管理:对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理。 30 31- 通信适配层:负责与卡片使用方和提供方进行RPC通信。 32 33卡片提供方包含以下模块: 34 35- 卡片服务:由卡片提供方开发者实现,开发者实现生命周期处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务。 36 37- 卡片提供方实例管理模块:由卡片提供方开发者实现,负责对卡片管理服务分配的卡片实例进行持久化管理。 38 39- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的更新数据主动推送到卡片管理服务。 40 41>  **说明:** 42> 实际开发时只需要作为卡片提供方进行卡片内容的开发,卡片使用方和卡片管理服务由系统自动处理。 43 44 45## 接口说明 46 47FormExtensionAbility类拥有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formExtensionAbility.md)。 48 49| 接口名 | 描述 | 50| -------- | -------- | 51| onAddForm(want: Want): formBindingData.FormBindingData | 卡片提供方接收创建卡片的通知接口。 | 52| onCastToNormalForm(formId: string): void | 卡片提供方接收临时卡片转常态卡片的通知接口。 | 53| onUpdateForm(formId: string): void | 卡片提供方接收更新卡片的通知接口。 | 54| onChangeFormVisibility(newStatus: { [key: string]: number }): void | 卡片提供方接收修改可见性的通知接口。 | 55| onFormEvent(formId: string, message: string): void | 卡片提供方接收处理卡片事件的通知接口。 | 56| onRemoveForm(formId: string): void | 卡片提供方接收销毁卡片的通知接口。 | 57| onConfigurationUpdate(newConfig: Configuration): void | 当系统配置更新时调用。 | 58| onShareForm?(formId: string): { [key: string]: Object } | 卡片提供方接收卡片分享的通知接口。 | 59 60formProvider类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formProvider.md)。 61 62| 接口名 | 描述 | 63| -------- | -------- | 64| setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback<void>): void | 设置指定卡片的下一次更新时间。 | 65| setFormNextRefreshTime(formId: string, minute: number): Promise<void> | 设置指定卡片的下一次更新时间,以promise方式返回。 | 66| updateForm(formId: string, formBindingData: formBindingData.FormBindingData, callback: AsyncCallback<void>): void | 更新指定的卡片。 | 67| updateForm(formId: string, formBindingData: formBindingData.FormBindingData): Promise<void> | 更新指定的卡片,以promise方式返回。 | 68 69formBindingData类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formBindingData.md)。 70 71| 接口名 | 描述 | 72| -------- | -------- | 73| createFormBindingData(obj?: Object \| string): FormBindingData | 创建一个FormBindingData对象。 | 74 75 76## 开发步骤 77 78Stage卡片开发,即基于[Stage模型](stage-model-development-overview.md)的卡片提供方开发,主要涉及如下关键步骤: 79 80- [创建卡片FormExtensionAbility](#创建卡片formextensionability):卡片生命周期回调函数FormExtensionAbility开发。 81 82- [配置卡片配置文件](#配置卡片配置文件):配置应用配置文件module.json5和profile配置文件。 83 84- [卡片信息的持久化](#卡片信息的持久化):对卡片信息进行持久化管理。 85 86- [卡片数据交互](#卡片数据交互):通过updateForm更新卡片显示的信息。 87 88- [开发卡片页面](#开发卡片页面):使用HML+CSS+JSON开发JS卡片页面。 89 90- [开发卡片事件](#开发卡片事件):为卡片添加router事件和message事件。 91 92 93### 创建卡片FormExtensionAbility 94 95创建Stage模型的卡片,需实现FormExtensionAbility生命周期接口。先参考[DevEco Studio服务卡片开发指南](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V1/ide_service_widget-0000001078566997-V1)生成服务卡片模板。 96 971. 在EntryFormAbility.ets中,导入相关模块。 98 99 100 ```ts 101 import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; 102 import formBindingData from '@ohos.app.form.formBindingData'; 103 import formInfo from '@ohos.app.form.formInfo'; 104 import formProvider from '@ohos.app.form.formProvider'; 105 import Want from '@ohos.app.ability.Want'; 106 import Base from '@ohos.base'; 107 ``` 108 1092. 在EntryFormAbility.ets中,实现FormExtension生命周期接口。 110 111 112 ```ts 113 export default class EntryFormAbility extends FormExtensionAbility { 114 onAddForm(want: Want) { 115 console.info('[EntryFormAbility] onAddForm'); 116 // 使用方创建卡片时触发,提供方需要返回卡片数据绑定类 117 let obj: Record<string, string> = { 118 "title": "titleOnCreate", 119 "detail": "detailOnCreate" 120 }; 121 let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj); 122 return formData; 123 } 124 onCastToNormalForm(formId: string) { 125 // 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理 126 console.info('[EntryFormAbility] onCastToNormalForm'); 127 } 128 onUpdateForm(formId: string) { 129 // 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新 130 console.info('[EntryFormAbility] onUpdateForm'); 131 let obj: Record<string, string> = { 132 "title": "titleOnUpdate", 133 "detail": "detailOnUpdate" 134 }; 135 let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj); 136 formProvider.updateForm(formId, formData).catch((error: Base.BusinessError) => { 137 console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error)); 138 }); 139 } 140 onChangeFormVisibility(newStatus: Record<string, number>) { 141 // 使用方发起可见或者不可见通知触发,提供方需要做相应的处理,仅系统应用生效 142 console.info('[EntryFormAbility] onChangeFormVisibility'); 143 } 144 onFormEvent(formId: string, message: string) { 145 // 若卡片支持触发事件,则需要重写该方法并实现对事件的触发 146 console.info('[EntryFormAbility] onFormEvent'); 147 } 148 onRemoveForm(formId: string) { 149 // 删除卡片实例数据 150 console.info('[EntryFormAbility] onRemoveForm'); 151 } 152 onAcquireFormState(want: Want) { 153 return formInfo.FormState.READY; 154 } 155 } 156 ``` 157 158>  **说明:** 159> FormExtensionAbility不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务。 160 161 162### 配置卡片配置文件 163 1641. 卡片需要在[module.json5配置文件](../quick-start/module-configuration-file.md)中的extensionAbilities标签下,配置ExtensionAbility相关信息。FormExtensionAbility需要填写metadata元信息标签,其中键名称为固定字符串"ohos.extension.form",资源为卡片的具体配置信息的索引。 165 配置示例如下: 166 167 168 ```json 169 { 170 "module": { 171 ... 172 "extensionAbilities": [ 173 { 174 "name": "EntryFormAbility", 175 "srcEntry": "./ets/entryformability/EntryFormAbility.ets", 176 "label": "$string:EntryFormAbility_label", 177 "description": "$string:EntryFormAbility_desc", 178 "type": "form", 179 "metadata": [ 180 { 181 "name": "ohos.extension.form", 182 "resource": "$profile:form_config" 183 } 184 ] 185 } 186 ] 187 } 188 } 189 ``` 190 1912. 卡片的具体配置信息。在上述FormExtensionAbility的元信息("metadata"配置项)中,可以指定卡片具体配置信息的资源索引。例如当resource指定为$profile:form_config时,会使用开发视图的resources/base/profile/目录下的form_config.json作为卡片profile配置文件。内部字段结构说明如下表所示。 192 193 **表1** 卡片profile配置文件 194 195 | 属性名称 | 含义 | 数据类型 | 是否可缺省 | 196 | -------- | -------- | -------- | -------- | 197 | name | 表示卡片的类名,字符串最大长度为127字节。 | 字符串 | 否 | 198 | description | 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省为空。 | 199 | src | 表示卡片对应的UI代码的完整路径。 | 字符串 | 否 | 200 | window | 用于定义与显示窗口相关的配置。 | 对象 | 可缺省 | 201 | isDefault | 表示该卡片是否为默认卡片,每个UIAbility有且只有一个默认卡片。<br/>- true:默认卡片。<br/>- false:非默认卡片。 | 布尔值 | 否 | 202 | colorMode | 表示卡片的主题样式,取值范围如下:<br/>- auto:自适应。<br/>- dark:深色主题。<br/>- light:浅色主题。 | 字符串 | 可缺省,缺省值为“auto”。 | 203 | supportDimensions | 表示卡片支持的外观规格,取值范围:<br/>- 1 \* 2:表示1行2列的二宫格。<br/>- 2 \* 2:表示2行2列的四宫格。<br/>- 2 \* 4:表示2行4列的八宫格。<br/>- 4 \* 4:表示4行4列的十六宫格。 | 字符串数组 | 否 | 204 | defaultDimension | 表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 否 | 205 | updateEnabled | 表示卡片是否支持周期性刷新,取值范围:<br/>- true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。<br/>- false:表示不支持周期性刷新。 | 布尔类型 | 否 | 206 | scheduledUpdateTime | 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 字符串 | 可缺省,缺省值为“0:0”。 | 207 | updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br/>当取值为0时,表示该参数不生效。<br/>当取值为正整数N时,表示刷新周期为30\*N分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 数值 | 可缺省,缺省值为“0”。 | 208 | formConfigAbility | 表示卡片的配置跳转链接,采用URI格式。 | 字符串 | 可缺省,缺省值为空。 | 209 | formVisibleNotify | 标识是否允许卡片使用卡片可见性通知。 | 字符串 | 可缺省,缺省值为空。 | 210 | metaData | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 | 211 212 配置示例如下: 213 214 215 ```json 216 { 217 "forms": [ 218 { 219 "name": "widget", 220 "description": "This is a service widget.", 221 "src": "./js/widget/pages/index/index", 222 "window": { 223 "designWidth": 720, 224 "autoDesignWidth": true 225 }, 226 "colorMode": "auto", 227 "isDefault": true, 228 "updateEnabled": true, 229 "scheduledUpdateTime": "10:30", 230 "updateDuration": 1, 231 "defaultDimension": "2*2", 232 "supportDimensions": [ 233 "2*2" 234 ] 235 } 236 ] 237 } 238 ``` 239 240 241### 卡片信息的持久化 242 243因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。 244 245 246```ts 247import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; 248import formBindingData from '@ohos.app.form.formBindingData'; 249import dataPreferences from '@ohos.data.preferences'; 250import Want from '@ohos.app.ability.Want'; 251import Base from '@ohos.base'; 252import common from '@ohos.app.ability.common' 253 254const DATA_STORAGE_PATH: string = "/data/storage/el2/base/haps/form_store"; 255let storeFormInfo = async (formId: string, formName: string, tempFlag: boolean, context: common.FormExtensionContext): Promise<void> => { 256 // 此处仅对卡片ID:formId,卡片名:formName和是否为临时卡片:tempFlag进行了持久化 257 let formInfo: Record<string, string | boolean | number> = { 258 "formName": formName, 259 "tempFlag": tempFlag, 260 "updateCount": 0 261 }; 262 try { 263 const storage: dataPreferences.Preferences = await dataPreferences.getPreferences(context, DATA_STORAGE_PATH); 264 // put form info 265 await storage.put(formId, JSON.stringify(formInfo)); 266 console.info(`[EntryFormAbility] storeFormInfo, put form info successfully, formId: ${formId}`); 267 await storage.flush(); 268 } catch (err) { 269 console.error(`[EntryFormAbility] failed to storeFormInfo, err: ${JSON.stringify(err as Base.BusinessError)}`); 270 } 271} 272 273export default class EntryFormAbility extends FormExtensionAbility { 274 onAddForm(want: Want) { 275 console.info('[EntryFormAbility] onAddForm'); 276 277 if (want.parameters) { 278 let formId = JSON.stringify(want.parameters["ohos.extra.param.key.form_identity"]); 279 let formName = JSON.stringify(want.parameters["ohos.extra.param.key.form_name"]); 280 let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"] as boolean; 281 // 将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用 282 // 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例 283 storeFormInfo(formId, formName, tempFlag, this.context); 284 } 285 286 let obj: Record<string, string> = { 287 "title": "titleOnCreate", 288 "detail": "detailOnCreate" 289 }; 290 let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj); 291 return formData; 292 } 293} 294``` 295 296且需要适配onRemoveForm卡片删除通知接口,在其中实现卡片实例数据的删除。 297 298 299```ts 300import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; 301import dataPreferences from '@ohos.data.preferences'; 302import Base from '@ohos.base'; 303import common from '@ohos.app.ability.common' 304 305const DATA_STORAGE_PATH: string = "/data/storage/el2/base/haps/form_store"; 306let deleteFormInfo = async (formId: string, context: common.FormExtensionContext): Promise<void> => { 307 try { 308 const storage: dataPreferences.Preferences = await dataPreferences.getPreferences(context, DATA_STORAGE_PATH); 309 // del form info 310 await storage.delete(formId); 311 console.info(`[EntryFormAbility] deleteFormInfo, del form info successfully, formId: ${formId}`); 312 await storage.flush(); 313 } catch (err) { 314 console.error(`[EntryFormAbility] failed to deleteFormInfo, err: ${JSON.stringify(err as Base.BusinessError)}`); 315 } 316} 317 318export default class EntryFormAbility extends FormExtensionAbility { 319 onRemoveForm(formId: string) { 320 console.info('[EntryFormAbility] onRemoveForm'); 321 // 删除之前持久化的卡片实例数据 322 // 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例 323 deleteFormInfo(formId, this.context); 324 } 325} 326``` 327 328具体的持久化方法可以参考[轻量级数据存储开发指导](../database/app-data-persistence-overview.md)。 329 330需要注意的是,卡片使用方在请求卡片时传递给提供方应用的Want数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片: 331 332- 常态卡片:卡片使用方会持久化的卡片; 333 334- 临时卡片:卡片使用方不会持久化的卡片; 335 336由于临时卡片的数据具有非持久化的特殊性,某些场景例如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。 337 338 339### 卡片数据交互 340 341当卡片应用需要更新数据时(如触发了定时更新或定点更新),卡片应用获取最新数据,并调用updateForm()接口主动触发卡片的更新。 342 343 344```ts 345import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; 346import formBindingData from '@ohos.app.form.formBindingData'; 347import formProvider from '@ohos.app.form.formProvider'; 348import Base from '@ohos.base'; 349 350export default class EntryFormAbility extends FormExtensionAbility { 351 onUpdateForm(formId: string) { 352 // 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新 353 console.info('[EntryFormAbility] onUpdateForm'); 354 let obj: Record<string, string> = { 355 "title": "titleOnUpdate", 356 "detail": "detailOnUpdate" 357 }; 358 let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj); 359 // 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变 360 formProvider.updateForm(formId, formData).catch((error: Base.BusinessError) => { 361 console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error)); 362 }); 363 } 364} 365``` 366 367 368### 开发卡片页面 369 370开发者可以使用类Web范式(HML+CSS+JSON)开发JS卡片页面。生成如下卡片页面,可以这样配置卡片页面文件: 371 372 373 374- HML:使用类Web范式的组件描述卡片的页面信息。 375 376 377 ```html 378 <div class="container"> 379 <stack> 380 <div class="container-img"> 381 <image src="/common/widget.png" class="bg-img"></image> 382 </div> 383 <div class="container-inner"> 384 <text class="title">{{title}}</text> 385 <text class="detail_text" onclick="routerEvent">{{detail}}</text> 386 </div> 387 </stack> 388 </div> 389 ``` 390 391- CSS:HML中类Web范式组件的样式信息。 392 393 394 ```css 395 .container { 396 flex-direction: column; 397 justify-content: center; 398 align-items: center; 399 } 400 401 .bg-img { 402 flex-shrink: 0; 403 height: 100%; 404 } 405 406 .container-inner { 407 flex-direction: column; 408 justify-content: flex-end; 409 align-items: flex-start; 410 height: 100%; 411 width: 100%; 412 padding: 12px; 413 } 414 415 .title { 416 font-size: 19px; 417 font-weight: bold; 418 color: white; 419 text-overflow: ellipsis; 420 max-lines: 1; 421 } 422 423 .detail_text { 424 font-size: 16px; 425 color: white; 426 opacity: 0.66; 427 text-overflow: ellipsis; 428 max-lines: 1; 429 margin-top: 6px; 430 } 431 ``` 432 433- JSON:卡片页面中的数据和事件交互。 434 435 436 ```json 437 { 438 "data": { 439 "title": "TitleDefault", 440 "detail": "TextDefault" 441 }, 442 "actions": { 443 "routerEvent": { 444 "action": "router", 445 "abilityName": "EntryAbility", 446 "params": { 447 "message": "add detail" 448 } 449 } 450 } 451 } 452 ``` 453 454 455### 开发卡片事件 456 457卡片支持为组件设置交互事件(action),包括**router**事件和**message**事件,其中router事件用于UIAbility跳转,message事件用于卡片开发人员自定义点击事件。 458 459关键步骤说明如下: 460 4611. 在HML中为组件设置onclick属性,其值对应到JSON文件的actions字段中。 462 4632. 设置router事件: 464 465 - action属性值为"router"。 466 - abilityName为跳转目标的UIAbility名(支持跳转FA模型的PageAbility组件和Stage模型的UIAbility组件),如目前DevEco Studio创建的Stage模型的UIAbility默认名为EntryAbility。 467 - params为传递给跳转目标UIAbility的自定义参数,可以按需填写。其值可以在目标UIAbility启动时的want中的parameters里获取。如Stage模型MainAbility的onCreate生命周期里的入参want的parameters字段下获取到配置的参数。 468 4693. 设置message事件: 470 471 - action属性值为"message"。 472 - params为message事件的用户自定义参数,可以按需填写。其值可以在卡片生命周期函数onFormEvent()中的message里获取。 473 474示例如下。 475 476- HML文件 477 478 479 ```html 480 <div class="container"> 481 <stack> 482 <div class="container-img"> 483 <image src="/common/widget.png" class="bg-img"></image> 484 </div> 485 <div class="container-inner"> 486 <text class="title" onclick="routerEvent">{{title}}</text> 487 <text class="detail_text" onclick="messageEvent">{{detail}}</text> 488 </div> 489 </stack> 490 </div> 491 ``` 492 493- CSS文件 494 495 496 ```css 497 .container { 498 flex-direction: column; 499 justify-content: center; 500 align-items: center; 501 } 502 503 .bg-img { 504 flex-shrink: 0; 505 height: 100%; 506 } 507 508 .container-inner { 509 flex-direction: column; 510 justify-content: flex-end; 511 align-items: flex-start; 512 height: 100%; 513 width: 100%; 514 padding: 12px; 515 } 516 517 .title { 518 font-size: 19px; 519 font-weight: bold; 520 color: white; 521 text-overflow: ellipsis; 522 max-lines: 1; 523 } 524 525 .detail_text { 526 font-size: 16px; 527 color: white; 528 opacity: 0.66; 529 text-overflow: ellipsis; 530 max-lines: 1; 531 margin-top: 6px; 532 } 533 ``` 534 535- JSON文件 536 537 538 ```json 539 { 540 "data": { 541 "title": "TitleDefault", 542 "detail": "TextDefault" 543 }, 544 "actions": { 545 "routerEvent": { 546 "action": "router", 547 "abilityName": "EntryAbility", 548 "params": { 549 "info": "router info", 550 "message": "router message" 551 } 552 }, 553 "messageEvent": { 554 "action": "message", 555 "params": { 556 "detail": "message detail" 557 } 558 } 559 } 560 } 561 ``` 562 563 说明: 564 565 "data"中JSON Value支持多级嵌套数据,在更新数据时,需要注意携带完整数据。 566 567 例如:当前卡片显示07.18日Mr.Zhang的课程信息,示例如下。 568 ```ts 569 "data": { 570 "Day": "07.18", 571 "teacher": { 572 "name": "Mr.Zhang", 573 "course": "Math" 574 } 575 } 576 ``` 577 当卡片内容需要更新为07.18日Mr.Li的课程信息时,需要传递待更新的完整数据,不能值传递单个数据项,如只传name或只传course,示例如下。 578 ```ts 579 "teacher": { 580 "name": "Mr.Li", 581 "course": "English" 582 } 583 ``` 584 585 586- 在UIAbility中接收router事件并获取参数 587 588 589 ```ts 590 import UIAbility from '@ohos.app.ability.UIAbility'; 591 import AbilityConstant from '@ohos.app.ability.AbilityConstant'; 592 import Want from '@ohos.app.ability.Want'; 593 594 export default class EntryAbility extends UIAbility { 595 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 596 if (want.parameters) { 597 let params: Record<string, Object> = JSON.parse(JSON.stringify(want.parameters.params)); 598 // 获取router事件中传递的info参数 599 if (params.info === "router info") { 600 // do something 601 // console.info("router info:" + params.info) 602 } 603 // 获取router事件中传递的message参数 604 if (params.message === "router message") { 605 // do something 606 // console.info("router message:" + params.message) 607 } 608 } 609 } 610 }; 611 ``` 612 613- 在FormExtensionAbility中接收message事件并获取参数 614 615 616 ```ts 617 import FormExtension from '@ohos.app.form.FormExtensionAbility'; 618 619 export default class FormAbility extends FormExtension { 620 onFormEvent(formId: string, message: string) { 621 // 获取message事件中传递的detail参数 622 let msg: Record<string, string> = JSON.parse(message) 623 if (msg.detail === "message detail") { 624 // do something 625 // console.info("message info:" + msg.detail) 626 } 627 } 628 }; 629 ``` 630 631## 相关实例 632 633针对卡片开发,有以下相关实例可供参考: 634 635- [JS多设备自适应服务卡片(JS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/SuperFeature/Widget/AdaptiveServiceWidget) 636 637- [电影卡片(JS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Card/MovieCard) 638 639- [计步器卡片(JS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Card/StepsCardJS)