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