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