@buaa_smat/hometrans 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -124
- package/agents/build-fixer.md +1 -0
- package/agents/code-review-fix.md +1 -0
- package/agents/code-reviewer.md +1 -0
- package/agents/logic-coding.md +1 -0
- package/agents/logic-context-builder.md +1 -0
- package/agents/review-fixer.md +1 -0
- package/agents/self-test-fixer.md +1 -0
- package/agents/self-tester.md +260 -233
- package/agents/spec-generator.md +1 -0
- package/agents/test-tools/autotest/README.md +223 -0
- package/agents/test-tools/autotest/config.yaml.example +58 -0
- package/agents/test-tools/autotest/pyproject.toml +16 -0
- package/agents/test-tools/autotest/report_tool.py +759 -0
- package/agents/test-tools/autotest/self_test_runner.py +773 -0
- package/agents/test-tools/autotest/testcases_schema.md +143 -0
- package/agents/test-tools/autotest/testcases_tool.py +215 -0
- package/agents/test-tools/autotest/uv.lock +3156 -0
- package/agents/test-tools/harmony_autotest-0.1.0-py3-none-any.whl +0 -0
- package/agents/test-tools/hypium-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/hypium_mcp-0.6.5-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice_devicetest-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice_ohos-6.1.0.210-py3-none-any.whl +0 -0
- package/dist/cli/config-store.js +27 -2
- package/dist/cli/config.js +17 -6
- package/dist/cli/index.js +3 -2
- package/dist/cli/init.js +135 -22
- package/dist/cli/mcp.js +2 -2
- package/dist/context/index.js +165 -69
- package/package.json +59 -60
- package/skills/code-dev-review-fix/SKILL.md +279 -0
- package/skills/code-dev-review-fix-workspace/evals/evals.json +56 -0
- package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +23 -0
- package/skills/convert_pipeline/SKILL.md +423 -439
- package/skills/hmos-resources-convert/SKILL.md +623 -0
- package/skills/hmos-resources-convert/evals/evals.json +171 -0
- package/skills/hmos-resources-convert/references/conversion-rules.md +663 -0
- package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -0
- package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -0
- package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -0
- package/skills/hmos-resources-convert/template/AppScope/app.json5 +10 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/element/string.json +8 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/background.png +0 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/foreground.png +0 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/layered_image.json +7 -0
- package/skills/hmos-resources-convert/template/build-profile.json5 +42 -0
- package/skills/hmos-resources-convert/template/code-linter.json5 +32 -0
- package/skills/hmos-resources-convert/template/entry/build-profile.json5 +33 -0
- package/skills/hmos-resources-convert/template/entry/hvigorfile.ts +6 -0
- package/skills/hmos-resources-convert/template/entry/obfuscation-rules.txt +23 -0
- package/skills/hmos-resources-convert/template/entry/oh-package.json5 +10 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/pages/Index.ets +23 -0
- package/skills/hmos-resources-convert/template/entry/src/main/module.json5 +55 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/color.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/float.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/string.json +16 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/background.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/foreground.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/layered_image.json +7 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/startIcon.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/backup_config.json +3 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/main_pages.json +5 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/dark/element/color.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/mock/mock-config.json5 +2 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/List.test.ets +5 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/module.json5 +16 -0
- package/skills/hmos-resources-convert/template/entry/src/test/List.test.ets +5 -0
- package/skills/hmos-resources-convert/template/entry/src/test/LocalUnit.test.ets +33 -0
- package/skills/hmos-resources-convert/template/hvigor/hvigor-config.json5 +23 -0
- package/skills/hmos-resources-convert/template/hvigorfile.ts +6 -0
- package/skills/hmos-resources-convert/template/oh-package-lock.json5 +28 -0
- package/skills/hmos-resources-convert/template/oh-package.json5 +10 -0
- package/skills/hmos-resources-convert/tools/apktool.bat +85 -0
- package/skills/hmos-resources-convert/tools/apktool_3.0.1.jar +0 -0
- package/skills/hmos-ui-align/SKILL.md +182 -0
- package/skills/hmos-ui-align/config-example.json +11 -0
- package/skills/hmos-ui-align/config.json +11 -0
- package/skills/hmos-ui-align/diff_analysis.md +53 -0
- package/skills/hmos-ui-align/page_align.md +62 -0
- package/skills/hmos-ui-align/readme.md +231 -0
- package/skills/hmos-ui-align/references/Comparison_Template.md +2 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
- package/skills/hmos-ui-align/references/UI_Analysis_Template.md +4 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-ui-align/scripts/app_feature_verify.py +443 -0
- package/skills/hmos-ui-align/scripts/navigation-capure.md +37 -0
- package/skills/hmos-ui-align/scripts/page_capture.py +592 -0
- package/skills/hmos-ui-align-batch/SKILL.md +99 -0
- package/skills/hmos-ui-align-batch/references/conversion-procedure.md +180 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
- package/skills/hmos-ui-align-batch/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
- package/skills/hmos-ui-align-batch/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
- package/skills/hmos-ui-align-batch/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
- package/skills/hmos-ui-align-batch/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
- package/skills/hmos-ui-align-batch/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
- package/skills/hmos-ui-align-batch/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
- package/skills/hmos-ui-align-batch/scripts/android_parse_fast.py +1606 -0
- package/skills/self-test/SKILL.md +369 -0
- package/skills/self-test/readme.md +309 -0
- package/skills/spec-generator-skill/SKILL.md +332 -0
- package/skills/spec-generator-skill/references/android-platform-tokens.md +105 -0
- package/skills/spec-generator-skill/references/spec-sample-1.md +78 -0
- package/skills/spec-generator-skill/references/spec-sample-2.md +58 -0
- package/skills/spec-generator-skill/references/spec-sample-3.md +116 -0
- package/skills/spec-generator-skill/references/step4-report-template.md +33 -0
- package/agents/self-test-setup.md +0 -165
- package/dist/context/resources/sdkConfig.json +0 -24
- package/src/context/resources/sdkConfig.json +0 -24
|
@@ -0,0 +1,1178 @@
|
|
|
1
|
+
# LocalStorage:页面级UI状态存储
|
|
2
|
+
|
|
3
|
+
LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。
|
|
4
|
+
|
|
5
|
+
本文仅介绍LocalStorage使用场景和相关的装饰器:@LocalStorageProp和@LocalStorageLink。
|
|
6
|
+
|
|
7
|
+
在阅读本文档前,需要开发者对状态管理框架有基本的了解。建议提前阅读:[状态管理概述](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-overview)。
|
|
8
|
+
|
|
9
|
+
LocalStorage还提供了API接口,可以让开发者通过接口在自定义组件外手动触发Storage对应key的增删改查,建议配合[LocalStorage API文档](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-state-management#localstorage9)阅读。最佳实践请参考[状态管理最佳实践](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-status-management)。
|
|
10
|
+
|
|
11
|
+
> **说明:**
|
|
12
|
+
>
|
|
13
|
+
> LocalStorage从API version 9开始支持。
|
|
14
|
+
|
|
15
|
+
## 概述
|
|
16
|
+
|
|
17
|
+
LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内的"数据库"。
|
|
18
|
+
|
|
19
|
+
- 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过[getSharedLocalStorage](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-uicontext#getsharedlocalstorage12)接口,实现跨页面、跨[UIAbility](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/uiability-overview)实例共享。
|
|
20
|
+
|
|
21
|
+
- 组件树的根节点,即被[@Entry](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-entry#entry)装饰的[@Component](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-create-custom-components#component),可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限。
|
|
22
|
+
|
|
23
|
+
- @Component装饰的组件既可以自动继承来自父组件的LocalStorage实例,也可以传入指定的LocalStorage的实例,详见:[自定义组件接收LocalStorage实例](#自定义组件接收localstorage实例)。
|
|
24
|
+
|
|
25
|
+
- LocalStorage中的所有属性都是可变的。
|
|
26
|
+
|
|
27
|
+
应用程序决定LocalStorage对象的生命周期。当应用释放最后一个指向LocalStorage的引用时,比如销毁最后一个自定义组件,LocalStorage将被JS Engine垃圾回收。
|
|
28
|
+
|
|
29
|
+
LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:
|
|
30
|
+
|
|
31
|
+
- [@LocalStorageProp](#localstorageprop):@LocalStorageProp装饰的变量与LocalStorage中给定属性建立单向同步关系。
|
|
32
|
+
|
|
33
|
+
- [@LocalStorageLink](#localstoragelink):@LocalStorageLink装饰的变量与LocalStorage中给定属性建立双向同步关系。
|
|
34
|
+
|
|
35
|
+
## @LocalStorageProp
|
|
36
|
+
|
|
37
|
+
在上文中已经提到,如果要建立LocalStorage和自定义组件的联系,需要使用@LocalStorageProp和@LocalStorageLink装饰器。使用@LocalStorageProp(key)/@LocalStorageLink(key)装饰组件内的变量,key标识了LocalStorage的属性。
|
|
38
|
+
|
|
39
|
+
当自定义组件初始化的时候,@LocalStorageProp(key)/@LocalStorageLink(key)装饰的变量会通过给定的key,绑定LocalStorage对应的属性,完成初始化。本地初始化是必要的,因为无法保证LocalStorage一定存在给定的key(这取决于应用逻辑是否在组件初始化之前在LocalStorage实例中存入对应的属性)。
|
|
40
|
+
|
|
41
|
+
> **说明:**
|
|
42
|
+
>
|
|
43
|
+
> 从API version 9开始,该装饰器支持在ArkTS卡片中使用。
|
|
44
|
+
>
|
|
45
|
+
> 从API version 11开始,该装饰器支持在元服务中使用。
|
|
46
|
+
|
|
47
|
+
@LocalStorageProp(key)和LocalStorage中key对应的属性建立单向数据同步,ArkUI框架支持修改@LocalStorageProp(key)在本地的值,但是对本地值的修改不会同步回LocalStorage中。相反,如果LocalStorage中key对应的属性值发生改变,例如通过set接口对LocalStorage中的值进行修改,改变会同步给@LocalStorageProp(key),并覆盖掉本地的值。
|
|
48
|
+
|
|
49
|
+
### 装饰器使用规则
|
|
50
|
+
|
|
51
|
+
| @LocalStorageProp变量装饰器 | 说明 |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| 装饰器参数 | key:常量字符串,必填(字符串需要有引号)。 |
|
|
54
|
+
| 允许装饰的变量类型 | Object、class、string、number、boolean、enum类型,以及这些类型的数组。API version 12及以上支持Map、Set、Date、undefined和null类型以及这些类型的联合类型,示例见[LocalStorage支持联合类型](#localstorage支持联合类型)。嵌套类型的场景请参考[观察变化和行为表现](#观察变化和行为表现)。**说明:** 变量类型必须被指定,建议和LocalStorage中对应属性类型相同,否则会发生类型隐式转换,从而导致应用行为异常。 |
|
|
55
|
+
| 同步类型 | 单向同步:从LocalStorage的对应属性到组件的状态变量。组件本地的修改是允许的,但是LocalStorage中给定的属性一旦发生变化,将覆盖本地的修改。 |
|
|
56
|
+
| 被装饰变量的初始值 | 必须指定,如果LocalStorage实例中不存在属性,则用该初始值初始化该属性,并存入LocalStorage中。 |
|
|
57
|
+
|
|
58
|
+
### 变量的传递/访问规则
|
|
59
|
+
|
|
60
|
+
| 传递/访问规则 | 说明 |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| 从父节点初始化和更新 | 禁止,@LocalStorageProp不支持从父节点初始化,只能从LocalStorage中key对应的属性初始化,如果没有对应的key,将使用本地默认值初始化。 |
|
|
63
|
+
| 初始化子节点 | 支持,可用于初始化@State、@Link、@Prop、@Provide。 |
|
|
64
|
+
| 是否支持组件外访问 | 否。 |
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
|
|
68
|
+
**图1** @LocalStorageProp初始化规则图示
|
|
69
|
+
|
|
70
|
+
### 观察变化和行为表现
|
|
71
|
+
|
|
72
|
+
**观察变化**
|
|
73
|
+
|
|
74
|
+
- 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
|
|
75
|
+
|
|
76
|
+
- 当装饰的数据类型为class或者Object时,可以观察到对象整体赋值和对象属性变化(详见[从ui内部使用localstorage](#从ui内部使用localstorage))。
|
|
77
|
+
|
|
78
|
+
- 当装饰的对象是数组时,可以观察到数组添加、删除、更新数组单元的变化。
|
|
79
|
+
|
|
80
|
+
- 当装饰的对象是Date时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新Date的属性。详见[装饰Date类型变量](#装饰date类型变量)。
|
|
81
|
+
|
|
82
|
+
- 当装饰的变量是Map时,可以观察到Map整体的赋值,同时可通过调用Map的接口set, clear, delete 更新Map的值。详见[装饰Map类型变量](#装饰map类型变量)。
|
|
83
|
+
|
|
84
|
+
- 当装饰的变量是Set时,可以观察到Set整体的赋值,同时可通过调用Set的接口add, clear, delete 更新Set的值。详见[装饰Set类型变量](#装饰set类型变量)。
|
|
85
|
+
|
|
86
|
+
**框架行为**
|
|
87
|
+
|
|
88
|
+
1. 使用@LocalStorageProp(key)装饰的变量更新时,不会写回LocalStorage,但会触发当前自定义组件的重新渲染。
|
|
89
|
+
|
|
90
|
+
2. 当LocalStorage中对应key的值发生变化时,所有使用@LocalStorageProp(key)装饰的变量都会同步更新,覆盖本地修改。
|
|
91
|
+
|
|
92
|
+
**LocalStorage与@LocalStorageProp数据同步如下图所示**
|
|
93
|
+
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+
**图2** LocalStorage与@LocalStorageProp数据同步图示
|
|
97
|
+
|
|
98
|
+
## @LocalStorageLink
|
|
99
|
+
|
|
100
|
+
> **说明:**
|
|
101
|
+
>
|
|
102
|
+
> 从API version 11开始,该装饰器支持在元服务中使用。
|
|
103
|
+
|
|
104
|
+
如果我们需要将自定义组件的状态变量的更新同步回LocalStorage,就需要用到@LocalStorageLink。
|
|
105
|
+
|
|
106
|
+
@LocalStorageLink(key)是和LocalStorage中key对应的属性建立双向数据同步:
|
|
107
|
+
|
|
108
|
+
1. 本地修改发生,该修改会被写回LocalStorage中。
|
|
109
|
+
|
|
110
|
+
2. LocalStorage中的修改发生后,该修改会被同步到所有绑定LocalStorage对应key的属性上,包括单向(@LocalStorageProp和通过prop创建的单向绑定变量)、双向(@LocalStorageLink和通过link创建的双向绑定变量)变量。
|
|
111
|
+
|
|
112
|
+
### 装饰器使用规则
|
|
113
|
+
|
|
114
|
+
| @LocalStorageLink变量装饰器 | 说明 |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| 装饰器参数 | key:常量字符串,必填(字符串需要有引号)。 |
|
|
117
|
+
| 允许装饰的变量类型 | Object、class、string、number、boolean、enum类型,以及这些类型的数组。API version 12及以上支持Map、Set、Date、undefined和null类型以及这些类型的联合类型。示例见[LocalStorage支持联合类型](#localstorage支持联合类型)。嵌套类型的场景请参考[观察变化和行为表现](#观察变化和行为表现-1)。**说明:** 变量类型必须被指定,建议和LocalStorage中对应属性类型相同,否则会发生类型隐式转换,从而导致应用行为异常。 |
|
|
118
|
+
| 同步类型 | 双向同步:从LocalStorage的对应属性到自定义组件,从自定义组件到LocalStorage对应属性。 |
|
|
119
|
+
| 被装饰变量的初始值 | 必须指定,如果LocalStorage实例中不存在属性,则用该初始值初始化该属性,并存入LocalStorage中。 |
|
|
120
|
+
|
|
121
|
+
### 变量的传递/访问规则
|
|
122
|
+
|
|
123
|
+
| 传递/访问规则 | 说明 |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| 从父节点初始化和更新 | 禁止,@LocalStorageLink不支持从父节点初始化,只能从LocalStorage中key对应的属性初始化,如果没有对应的key,将使用本地默认值初始化。 |
|
|
126
|
+
| 初始化子节点 | 支持,可用于初始化@State、@Link、@Prop、@Provide。 |
|
|
127
|
+
| 是否支持组件外访问 | 否。 |
|
|
128
|
+
|
|
129
|
+

|
|
130
|
+
|
|
131
|
+
**图3** @LocalStorageLink初始化规则图示
|
|
132
|
+
|
|
133
|
+
### 观察变化和行为表现
|
|
134
|
+
|
|
135
|
+
**观察变化**
|
|
136
|
+
|
|
137
|
+
- 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
|
|
138
|
+
|
|
139
|
+
- 当装饰的数据类型为class或者Object时,可以观察到对象整体赋值和对象属性变化(详见[从ui内部使用localstorage](#从ui内部使用localstorage))。
|
|
140
|
+
|
|
141
|
+
- 当装饰的对象是数组时,可以观察到数组添加、删除、更新数组单元的变化。详见[装饰Array类型变量](#装饰array类型变量)。
|
|
142
|
+
|
|
143
|
+
- 当装饰的对象是Date时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新Date的属性。详见[装饰Date类型变量](#装饰date类型变量)。
|
|
144
|
+
|
|
145
|
+
- 当装饰的变量是Map时,可以观察到Map整体的赋值,同时可通过调用Map的接口set, clear, delete 更新Map的值。详见[装饰Map类型变量](#装饰map类型变量)。
|
|
146
|
+
|
|
147
|
+
- 当装饰的变量是Set时,可以观察到Set整体的赋值,同时可通过调用Set的接口add, clear, delete 更新Set的值。详见[装饰Set类型变量](#装饰set类型变量)。
|
|
148
|
+
|
|
149
|
+
**框架行为**
|
|
150
|
+
|
|
151
|
+
1. 使用@LocalStorageLink(key)装饰的变量更新时,会同步写回LocalStorage对应的key,还会触发当前自定义组件的重新渲染。
|
|
152
|
+
|
|
153
|
+
2. 当LocalStorage中对应key的值发生变化时,所有绑定该key的数据(包括双向@LocalStorageLink和单向@LocalStorageProp)都会同步更新。
|
|
154
|
+
|
|
155
|
+
**LocalStorage与@LocalStorageLink数据同步如下图所示**
|
|
156
|
+
|
|
157
|
+

|
|
158
|
+
|
|
159
|
+
**图4** LocalStorage与@LocalStorageLink数据同步图示
|
|
160
|
+
|
|
161
|
+
## 限制条件
|
|
162
|
+
|
|
163
|
+
1. @LocalStorageProp/@LocalStorageLink的参数必须为string类型,否则编译期会报错。
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
let storage = new LocalStorage();
|
|
167
|
+
storage.setOrCreate('PropA', 48);
|
|
168
|
+
|
|
169
|
+
// 错误写法,编译报错
|
|
170
|
+
@LocalStorageProp() localStorageProp: number = 1;
|
|
171
|
+
@LocalStorageLink() localStorageLink: number = 2;
|
|
172
|
+
|
|
173
|
+
// 正确写法
|
|
174
|
+
@LocalStorageProp('PropA') localStorageProp: number = 1;
|
|
175
|
+
@LocalStorageLink('PropA') localStorageLink: number = 2;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
2. @LocalStorageProp与@LocalStorageLink不支持装饰Function类型的变量,框架会抛出运行时错误。
|
|
179
|
+
|
|
180
|
+
3. LocalStorage创建后,命名属性的类型不可更改。后续调用Set时必须使用相同类型的值。
|
|
181
|
+
|
|
182
|
+
4. LocalStorage是页面级存储,[getSharedLocalStorage](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-uicontext#getsharedlocalstorage12)接口仅能获取当前Stage通过[windowStage.loadContent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-window#loadcontent9)传入的LocalStorage实例,否则返回undefined。例子可见[将LocalStorage实例从UIAbility共享到一个或多个页面](#将localstorage实例从uiability共享到一个或多个页面)。
|
|
183
|
+
|
|
184
|
+
## 使用场景
|
|
185
|
+
|
|
186
|
+
### 应用逻辑使用LocalStorage
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
let para: Record<string,number> = { 'PropA': 47 };
|
|
190
|
+
let storage: LocalStorage = new LocalStorage(para); // 创建新实例并使用给定对象初始化
|
|
191
|
+
let propA: number | undefined = storage.get('PropA'); // propA == 47
|
|
192
|
+
let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); // link1.get() == 47
|
|
193
|
+
let link2: SubscribedAbstractProperty<number> = storage.link('PropA'); // link2.get() == 47
|
|
194
|
+
let prop: SubscribedAbstractProperty<number> = storage.prop('PropA'); // prop.get() == 47
|
|
195
|
+
link1.set(48); // 双向同步: link1.get() == link2.get() == prop.get() == 48
|
|
196
|
+
prop.set(1); // 单向同步: prop.get() == 1; 但 link1.get() == link2.get() == 48
|
|
197
|
+
link1.set(49); // 双向同步: link1.get() == link2.get() == prop.get() == 49
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 从UI内部使用LocalStorage
|
|
201
|
+
|
|
202
|
+
除了应用程序逻辑使用LocalStorage,还可以借助LocalStorage相关的两个装饰器@LocalStorageProp和@LocalStorageLink,在UI组件内部获取到LocalStorage实例中存储的状态变量。
|
|
203
|
+
|
|
204
|
+
本示例以@LocalStorageLink为例,展示了:
|
|
205
|
+
|
|
206
|
+
- 使用构造函数创建LocalStorage实例storage。
|
|
207
|
+
|
|
208
|
+
- 使用@Entry装饰器将storage添加到Parent顶层组件中。
|
|
209
|
+
|
|
210
|
+
- @LocalStorageLink绑定LocalStorage对给定的属性,建立双向数据同步。
|
|
211
|
+
|
|
212
|
+
```TypeScript
|
|
213
|
+
class Data {
|
|
214
|
+
public code: number;
|
|
215
|
+
|
|
216
|
+
constructor(code: number) {
|
|
217
|
+
this.code = code;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 创建新实例并使用给定对象初始化
|
|
222
|
+
let para: Record<string, number> = { 'PropA': 47 };
|
|
223
|
+
let storage: LocalStorage = new LocalStorage(para);
|
|
224
|
+
storage.setOrCreate('PropB', new Data(50));
|
|
225
|
+
|
|
226
|
+
@Component
|
|
227
|
+
struct Child {
|
|
228
|
+
// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
|
|
229
|
+
@LocalStorageLink('PropA') childLinkNumber: number = 1;
|
|
230
|
+
// @LocalStorageLink变量装饰器与LocalStorage中的'PropB'属性建立双向绑定
|
|
231
|
+
@LocalStorageLink('PropB') childLinkObject: Data = new Data(0);
|
|
232
|
+
|
|
233
|
+
build() {
|
|
234
|
+
Column({ space: 15 }) {
|
|
235
|
+
// 更改将同步至LocalStorage中的'PropA'以及Parent.parentLinkNumber
|
|
236
|
+
Button(`Child from LocalStorage ${this.childLinkNumber}`)
|
|
237
|
+
.onClick(() => {
|
|
238
|
+
this.childLinkNumber += 1;
|
|
239
|
+
})
|
|
240
|
+
// 更改将同步至LocalStorage中的'PropB'以及Parent.parentLinkObject.code
|
|
241
|
+
Button(`Child from LocalStorage ${this.childLinkObject.code}`)
|
|
242
|
+
.onClick(() => {
|
|
243
|
+
this.childLinkObject.code += 1;
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 使LocalStorage可从@Component组件访问
|
|
250
|
+
@Entry(storage)
|
|
251
|
+
@Component
|
|
252
|
+
struct Parent {
|
|
253
|
+
// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
|
|
254
|
+
@LocalStorageLink('PropA') parentLinkNumber: number = 1;
|
|
255
|
+
// @LocalStorageLink变量装饰器与LocalStorage中的'PropB'属性建立双向绑定
|
|
256
|
+
@LocalStorageLink('PropB') parentLinkObject: Data = new Data(0);
|
|
257
|
+
|
|
258
|
+
build() {
|
|
259
|
+
Column({ space: 15 }) {
|
|
260
|
+
// 由于LocalStorage中PropA已经被初始化,因此this.parentLinkNumber的值为47
|
|
261
|
+
Button(`Parent from LocalStorage ${this.parentLinkNumber}`)
|
|
262
|
+
.onClick(() => {
|
|
263
|
+
this.parentLinkNumber += 1;
|
|
264
|
+
})
|
|
265
|
+
// 由于LocalStorage中PropB已经被初始化,因此this.parentLinkObject.code的值为50
|
|
266
|
+
Button(`Parent from LocalStorage ${this.parentLinkObject.code}`)
|
|
267
|
+
.onClick(() => {
|
|
268
|
+
this.parentLinkObject.code += 1;
|
|
269
|
+
})
|
|
270
|
+
// @Component子组件自动获得对Parent LocalStorage实例的访问权限
|
|
271
|
+
Child()
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### @LocalStorageProp和LocalStorage单向同步的简单场景
|
|
278
|
+
|
|
279
|
+
本示例展示了ParentOne和ChildOne组件各自在本地创建与paraOneLocal中'PropA'属性的单向数据同步:
|
|
280
|
+
|
|
281
|
+
- ParentOne中对this.storagePropOne的修改,只会在ParentOne中生效,并没有同步回storageOneLocal。
|
|
282
|
+
|
|
283
|
+
- ChildOne组件中,Text绑定的storagePropTwo 依旧显示47。
|
|
284
|
+
|
|
285
|
+
```TypeScript
|
|
286
|
+
// 创建新实例并使用给定对象初始化
|
|
287
|
+
let paraOneLocal: Record<string, number> = { 'PropA': 47 };
|
|
288
|
+
let storageOneLocal: LocalStorage = new LocalStorage(paraOneLocal);
|
|
289
|
+
// 使LocalStorage可从@Component组件访问
|
|
290
|
+
@Entry(storageOneLocal)
|
|
291
|
+
@Component
|
|
292
|
+
struct ParentOne {
|
|
293
|
+
// @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定
|
|
294
|
+
@LocalStorageProp('PropA') storagePropOne: number = 1;
|
|
295
|
+
|
|
296
|
+
build() {
|
|
297
|
+
Column({ space: 15 }) {
|
|
298
|
+
// 点击后从47开始加1,只改变当前组件显示的storagePropOne ,不会同步到LocalStorage中
|
|
299
|
+
Button(`ParentOne from LocalStorage ${this.storagePropOne}`)
|
|
300
|
+
.onClick(() => {
|
|
301
|
+
this.storagePropOne += 1;
|
|
302
|
+
})
|
|
303
|
+
ChildOne()
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
@Component
|
|
309
|
+
struct ChildOne {
|
|
310
|
+
// @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定
|
|
311
|
+
@LocalStorageProp('PropA') storagePropTwo: number = 2;
|
|
312
|
+
|
|
313
|
+
build() {
|
|
314
|
+
Column({ space: 15 }) {
|
|
315
|
+
// 当ParentOne改变时,当前storagePropTwo不会改变,显示47
|
|
316
|
+
Text(`ParentOne from LocalStorage ${this.storagePropTwo}`)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### @LocalStorageLink和LocalStorage双向同步的简单场景
|
|
323
|
+
|
|
324
|
+
下面的示例展示了@LocalStorageLink装饰的数据和LocalStorage双向同步的场景:
|
|
325
|
+
|
|
326
|
+
```TypeScript
|
|
327
|
+
// 构造LocalStorage实例
|
|
328
|
+
let paraOne: Record<string, number> = { 'PropA': 47 };
|
|
329
|
+
let storageOne: LocalStorage = new LocalStorage(paraOne);
|
|
330
|
+
// 调用link(api9以上)接口构造'PropA'的双向同步数据,linkToPropA 是全局变量
|
|
331
|
+
let linkToPropA: SubscribedAbstractProperty<object> = storageOne.link('PropA');
|
|
332
|
+
|
|
333
|
+
@Entry(storageOne)
|
|
334
|
+
@Component
|
|
335
|
+
struct ParentTwo {
|
|
336
|
+
|
|
337
|
+
// @LocalStorageLink('PropA')在Parent自定义组件中创建'PropA'的双向同步数据,初始值为47,因为在构造LocalStorage已经给"PropA"设置47
|
|
338
|
+
@LocalStorageLink('PropA') storageLink: number = 1;
|
|
339
|
+
|
|
340
|
+
build() {
|
|
341
|
+
Column() {
|
|
342
|
+
Text(`incr @LocalStorageLink variable`)
|
|
343
|
+
// 点击"incr @LocalStorageLink variable",this.storageLink加1,改变同步回storage,全局变量linkToPropA也会同步改变
|
|
344
|
+
|
|
345
|
+
.onClick(() => {
|
|
346
|
+
this.storageLink += 1;
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
// 并不建议在组件内使用全局变量linkToPropA.get(),因为可能会有生命周期不同引起的错误。
|
|
350
|
+
Text(`@LocalStorageLink: ${this.storageLink} - linkToPropA: ${linkToPropA.get()}`)
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 兄弟组件之间同步状态变量
|
|
357
|
+
|
|
358
|
+
下面的示例展示了通过@LocalStorageLink双向同步兄弟组件之间的状态。
|
|
359
|
+
|
|
360
|
+
先看ParentFour自定义组件中发生的变化:
|
|
361
|
+
|
|
362
|
+
1.点击"playCount ${this.playCount} dec by 1",this.playCount减1,修改同步回LocalStorage中,ChildFour组件中的playCountLink绑定的组件会同步刷新。
|
|
363
|
+
|
|
364
|
+
2.点击"countStorage ${this.playCount} incr by 1",调用LocalStorage的set接口,更新LocalStorage中"countStorage"对应的属性,ChildFour组件中的playCountLink绑定的组件会同步刷新。
|
|
365
|
+
|
|
366
|
+
3.Text组件"playCount in LocalStorage for debug ${storageFour.get<number>('countStorage')}"没有同步刷新,因为storageFour.get<number>('countStorage')返回的是常规变量,常规变量的更新并不会引起Text组件的重新渲染。
|
|
367
|
+
|
|
368
|
+
ChildFour自定义组件中的变化:
|
|
369
|
+
|
|
370
|
+
playCountLink的刷新会同步回LocalStorage,并且引起兄弟组件和父组件相应的刷新。
|
|
371
|
+
|
|
372
|
+
```TypeScript
|
|
373
|
+
let count: Record<string, number> = { 'countStorage': 1 };
|
|
374
|
+
let storageFour: LocalStorage = new LocalStorage(count);
|
|
375
|
+
|
|
376
|
+
@Component
|
|
377
|
+
struct ChildFour {
|
|
378
|
+
// 子组件实例的名字
|
|
379
|
+
label: string = 'no name';
|
|
380
|
+
// 和LocalStorage中"countStorage"的双向绑定数据
|
|
381
|
+
@LocalStorageLink('countStorage') playCountLink: number = 0;
|
|
382
|
+
|
|
383
|
+
build() {
|
|
384
|
+
Row() {
|
|
385
|
+
Text(this.label)
|
|
386
|
+
.width(50)
|
|
387
|
+
.height(60)
|
|
388
|
+
.fontSize(12)
|
|
389
|
+
Text(`playCountLink ${this.playCountLink}: inc by 1`)
|
|
390
|
+
.onClick(() => {
|
|
391
|
+
this.playCountLink += 1;
|
|
392
|
+
})
|
|
393
|
+
.width(200)
|
|
394
|
+
.height(60)
|
|
395
|
+
.fontSize(12)
|
|
396
|
+
}
|
|
397
|
+
.width(300)
|
|
398
|
+
.height(60)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
@Entry(storageFour)
|
|
403
|
+
@Component
|
|
404
|
+
struct ParentFour {
|
|
405
|
+
@LocalStorageLink('countStorage') playCount: number = 0;
|
|
406
|
+
|
|
407
|
+
build() {
|
|
408
|
+
Column() {
|
|
409
|
+
Row() {
|
|
410
|
+
Text('Parent')
|
|
411
|
+
.width(50)
|
|
412
|
+
.height(60)
|
|
413
|
+
.fontSize(12)
|
|
414
|
+
Text(`playCount ${this.playCount} dec by 1`)
|
|
415
|
+
.onClick(() => {
|
|
416
|
+
this.playCount -= 1;
|
|
417
|
+
})
|
|
418
|
+
.width(250)
|
|
419
|
+
.height(60)
|
|
420
|
+
.fontSize(12)
|
|
421
|
+
}
|
|
422
|
+
.width(300)
|
|
423
|
+
.height(60)
|
|
424
|
+
|
|
425
|
+
Row() {
|
|
426
|
+
Text('LocalStorage')
|
|
427
|
+
.width(50)
|
|
428
|
+
.height(60)
|
|
429
|
+
.fontSize(12)
|
|
430
|
+
Text(`countStorage ${this.playCount} incr by 1`)
|
|
431
|
+
.onClick(() => {
|
|
432
|
+
storageFour.set<number | undefined>('countStorage', Number(storageFour.get<number>('countStorage')) + 1);
|
|
433
|
+
})
|
|
434
|
+
.width(250)
|
|
435
|
+
.height(60)
|
|
436
|
+
.fontSize(12)
|
|
437
|
+
}
|
|
438
|
+
.width(300)
|
|
439
|
+
.height(60)
|
|
440
|
+
|
|
441
|
+
ChildFour({ label: 'ChildA' })
|
|
442
|
+
ChildFour({ label: 'ChildB' })
|
|
443
|
+
|
|
444
|
+
Text(`playCount in LocalStorage for debug ${storageFour.get<number>('countStorage')}`)
|
|
445
|
+
.width(300)
|
|
446
|
+
.height(60)
|
|
447
|
+
.fontSize(12)
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### 将LocalStorage实例从UIAbility共享到一个或多个页面
|
|
454
|
+
|
|
455
|
+
上面的实例中,LocalStorage的实例仅仅在一个@Entry装饰的组件和其所属的子组件(一个页面)中共享,如果希望其在多个页面中共享,可以在所属UIAbility中创建LocalStorage实例,并调用windowStage.[loadContent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-window#loadcontent9)。
|
|
456
|
+
|
|
457
|
+
```TypeScript
|
|
458
|
+
// EntryAbility.ets
|
|
459
|
+
import { UIAbility } from '@kit.AbilityKit';
|
|
460
|
+
import { window } from '@kit.ArkUI';
|
|
461
|
+
|
|
462
|
+
// ···
|
|
463
|
+
export default class EntryAbility extends UIAbility {
|
|
464
|
+
para: Record<string, number> = {
|
|
465
|
+
'PropA': 47
|
|
466
|
+
};
|
|
467
|
+
storage: LocalStorage = new LocalStorage(this.para);
|
|
468
|
+
|
|
469
|
+
onWindowStageCreate(windowStage: window.WindowStage): void {
|
|
470
|
+
// 当前用例需要开发者手动修改为windowStage.loadContent('pages/PageFiveShare', this.storage);
|
|
471
|
+
windowStage.loadContent('pages/Index', this.storage);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// ···
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
> **说明:**
|
|
479
|
+
>
|
|
480
|
+
> 在UI页面通过getSharedLocalStorage获取当前stage共享的LocalStorage实例。
|
|
481
|
+
>
|
|
482
|
+
> this.getUIContext().getSharedLocalStorage()只在模拟器或者实机上才有效,在Previewer预览器中使用不生效。
|
|
483
|
+
|
|
484
|
+
在下面的用例中,PageFiveShare页面中的propA通过使用共享的LocalStorage实例。点击Button跳转到PageFiveShareChange页面,点击Change propA改变propA的值,back回PageFiveShare页面后,页面中propA的值也同步修改。
|
|
485
|
+
|
|
486
|
+
```TypeScript
|
|
487
|
+
// PageFiveShare.ets
|
|
488
|
+
// 预览器上不支持获取页面共享的LocalStorage实例
|
|
489
|
+
@Entry({ useSharedStorage: true })
|
|
490
|
+
@Component
|
|
491
|
+
struct PageFiveShare {
|
|
492
|
+
// 可以使用@LocalStorageLink/Prop与LocalStorage实例中的变量建立联系
|
|
493
|
+
@LocalStorageLink('PropA') propA: number = 1;
|
|
494
|
+
pageStack: NavPathStack = new NavPathStack();
|
|
495
|
+
|
|
496
|
+
build() {
|
|
497
|
+
Navigation(this.pageStack) {
|
|
498
|
+
Row() {
|
|
499
|
+
Column() {
|
|
500
|
+
Text(`${this.propA}`)
|
|
501
|
+
.fontSize(50)
|
|
502
|
+
.fontWeight(FontWeight.Bold)
|
|
503
|
+
Button('To Page')
|
|
504
|
+
.onClick(() => {
|
|
505
|
+
this.pageStack.pushPathByName('Page', null);
|
|
506
|
+
})
|
|
507
|
+
}
|
|
508
|
+
.width('100%')
|
|
509
|
+
}
|
|
510
|
+
.height('100%')
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
```TypeScript
|
|
517
|
+
@Builder
|
|
518
|
+
export function PageBuilder() {
|
|
519
|
+
PageFiveShareChange()
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// PageFiveShareChange组件获得了父亲PageFiveShare组件的LocalStorage实例
|
|
523
|
+
@Component
|
|
524
|
+
struct PageFiveShareChange {
|
|
525
|
+
@LocalStorageLink('PropA') propA: number = 2;
|
|
526
|
+
pathStack: NavPathStack = new NavPathStack();
|
|
527
|
+
|
|
528
|
+
build() {
|
|
529
|
+
NavDestination() {
|
|
530
|
+
Row() {
|
|
531
|
+
Column() {
|
|
532
|
+
Text(`${this.propA}`)
|
|
533
|
+
.fontSize(50)
|
|
534
|
+
.fontWeight(FontWeight.Bold)
|
|
535
|
+
|
|
536
|
+
Button('Change propA')
|
|
537
|
+
.onClick(() => {
|
|
538
|
+
this.propA = 100;
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
Button('Back PageFiveShare')
|
|
542
|
+
.onClick(() => {
|
|
543
|
+
this.pathStack.pop();
|
|
544
|
+
})
|
|
545
|
+
}
|
|
546
|
+
.width('100%')
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
.onReady((context: NavDestinationContext) => {
|
|
550
|
+
this.pathStack = context.pathStack;
|
|
551
|
+
})
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
使用Navigation时,需要添加配置系统路由表文件src/main/resources/base/profile/route_map.json,并替换pageSourceFile为PageFiveShareChange页面的路径,并且在module.json5中添加:"routerMap": "$profile:route_map"。
|
|
557
|
+
|
|
558
|
+
```json
|
|
559
|
+
{
|
|
560
|
+
"routerMap": [
|
|
561
|
+
{
|
|
562
|
+
"name": "Page",
|
|
563
|
+
"pageSourceFile": "src/main/ets/pages/PageFiveShareChange.ets",
|
|
564
|
+
"buildFunction": "PageBuilder",
|
|
565
|
+
"data": {
|
|
566
|
+
"description" : "LocalStorage example"
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
]
|
|
570
|
+
}
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
> **说明:**
|
|
574
|
+
>
|
|
575
|
+
> 对于开发者更建议使用这个方式来构建LocalStorage的实例,并且在创建LocalStorage实例的时候就写入默认值,因为默认值可以作为运行异常的备份,也可以用作页面的单元测试。
|
|
576
|
+
|
|
577
|
+
### 自定义组件接收LocalStorage实例
|
|
578
|
+
|
|
579
|
+
除了根节点可通过@Entry来接收LocalStorage实例,自定义组件(子节点)也可以通过构造参数来传递LocalStorage实例。
|
|
580
|
+
|
|
581
|
+
本示例以@LocalStorageLink为例,展示了:
|
|
582
|
+
|
|
583
|
+
- 父组件TestIndex中的Text,显示LocalStorage实例localStorageOne中PropA的值为"propA"。
|
|
584
|
+
|
|
585
|
+
- ChildSix组件中,Text绑定的propB,显示LocalStorage实例localStorageTwo中PropB的值为"propB"。
|
|
586
|
+
|
|
587
|
+
> **说明:**
|
|
588
|
+
>
|
|
589
|
+
> 从API version 12开始,自定义组件支持接收LocalStorage实例。
|
|
590
|
+
>
|
|
591
|
+
> 当自定义组件作为子节点,定义了成员属性时,LocalStorage实例必须要放在第二个参数位置传递,否则会报类型不匹配的编译问题。
|
|
592
|
+
>
|
|
593
|
+
> 当在自定义组件中定义了属性时,暂时不支持只有一个LocalStorage实例作为入参。如果没定义属性,可以只传入一个LocalStorage实例作为入参。
|
|
594
|
+
>
|
|
595
|
+
> 如果定义的属性不需要从父组件初始化变量,则第一个参数需要传{}。
|
|
596
|
+
>
|
|
597
|
+
> 作为构造参数传给子组件的LocalStorage实例在初始化时就会被决定,可以通过@LocalStorageLink或者LocalStorage的API修改LocalStorage实例中保存的属性值,但LocalStorage实例自身不能被动态修改。
|
|
598
|
+
|
|
599
|
+
```TypeScript
|
|
600
|
+
let localStorageOne: LocalStorage = new LocalStorage();
|
|
601
|
+
localStorageOne.setOrCreate('propA', 'propA');
|
|
602
|
+
|
|
603
|
+
let localStorageTwo: LocalStorage = new LocalStorage();
|
|
604
|
+
localStorageTwo.setOrCreate('propB', 'propB');
|
|
605
|
+
|
|
606
|
+
@Entry(localStorageOne)
|
|
607
|
+
@Component
|
|
608
|
+
struct TestIndex {
|
|
609
|
+
// 'PropA',和localStorageOne中'propA'的双向同步
|
|
610
|
+
@LocalStorageLink('PropA') propA: string = 'Hello World';
|
|
611
|
+
@State count: number = 0;
|
|
612
|
+
|
|
613
|
+
build() {
|
|
614
|
+
Row() {
|
|
615
|
+
Column() {
|
|
616
|
+
Text(this.propA)
|
|
617
|
+
.fontSize(50)
|
|
618
|
+
.fontWeight(FontWeight.Bold)
|
|
619
|
+
// 使用LocalStorage 实例localStorageTwo
|
|
620
|
+
ChildSix({ count: this.count }, localStorageTwo)
|
|
621
|
+
}
|
|
622
|
+
.width('100%')
|
|
623
|
+
}
|
|
624
|
+
.height('100%')
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
@Component
|
|
630
|
+
struct ChildSix {
|
|
631
|
+
@Link count: number;
|
|
632
|
+
// 'Hello World'和localStorageTwo中'propB'的双向同步,如果localStorageTwo中没有'propB',则使用默认值'Hello World'
|
|
633
|
+
@LocalStorageLink('PropB') propB: string = 'Hello World';
|
|
634
|
+
|
|
635
|
+
build() {
|
|
636
|
+
Text(this.propB)
|
|
637
|
+
.fontSize(50)
|
|
638
|
+
.fontWeight(FontWeight.Bold)
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
1. 当自定义组件没有定义属性时,可以只传入一个LocalStorage实例作为入参。
|
|
644
|
+
|
|
645
|
+
```TypeScript
|
|
646
|
+
let localStorageInstance: LocalStorage = new LocalStorage();
|
|
647
|
+
localStorageInstance.setOrCreate('propA', 'propA');
|
|
648
|
+
|
|
649
|
+
let localStorageChange: LocalStorage = new LocalStorage();
|
|
650
|
+
localStorageChange.setOrCreate('propB', 'propB');
|
|
651
|
+
|
|
652
|
+
@Entry(localStorageInstance)
|
|
653
|
+
@Component
|
|
654
|
+
struct Index {
|
|
655
|
+
// 'PropA',和localStorageInstance中'PropA'的双向同步
|
|
656
|
+
@LocalStorageLink('PropA') propA: string = 'Hello World';
|
|
657
|
+
@State count: number = 0;
|
|
658
|
+
|
|
659
|
+
build() {
|
|
660
|
+
Row() {
|
|
661
|
+
Column() {
|
|
662
|
+
Text(this.propA)
|
|
663
|
+
.fontSize(50)
|
|
664
|
+
.fontWeight(FontWeight.Bold)
|
|
665
|
+
// 使用LocalStorage 实例localStorageChange
|
|
666
|
+
ChildOne(localStorageChange)
|
|
667
|
+
}
|
|
668
|
+
.width('100%')
|
|
669
|
+
}
|
|
670
|
+
.height('100%')
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
@Component
|
|
675
|
+
struct ChildOne {
|
|
676
|
+
build() {
|
|
677
|
+
Text('hello')
|
|
678
|
+
.fontSize(50)
|
|
679
|
+
.fontWeight(FontWeight.Bold)
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
2. 当定义的属性不需要从父组件初始化变量时,第一个参数需要传{}。
|
|
685
|
+
|
|
686
|
+
```TypeScript
|
|
687
|
+
let localStorageBOne: LocalStorage = new LocalStorage();
|
|
688
|
+
localStorageBOne.setOrCreate('propA', 'propA');
|
|
689
|
+
|
|
690
|
+
let localStorageBTwo: LocalStorage = new LocalStorage();
|
|
691
|
+
localStorageBTwo.setOrCreate('propB', 'propB');
|
|
692
|
+
|
|
693
|
+
@Entry(localStorageBOne)
|
|
694
|
+
@Component
|
|
695
|
+
struct PageSixLocalStorageB {
|
|
696
|
+
// 'PropA',和localStorageBOne中'propA'的双向同步
|
|
697
|
+
@LocalStorageLink('PropA') propA: string = 'Hello World';
|
|
698
|
+
@State count: number = 0;
|
|
699
|
+
|
|
700
|
+
build() {
|
|
701
|
+
Row() {
|
|
702
|
+
Column() {
|
|
703
|
+
Text(this.propA)
|
|
704
|
+
.fontSize(50)
|
|
705
|
+
.fontWeight(FontWeight.Bold)
|
|
706
|
+
// 使用LocalStorage 实例localStorageBTwo
|
|
707
|
+
Child({}, localStorageBTwo)
|
|
708
|
+
}
|
|
709
|
+
.width('100%')
|
|
710
|
+
}
|
|
711
|
+
.height('100%')
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
@Component
|
|
716
|
+
struct Child {
|
|
717
|
+
@State count: number = 5;
|
|
718
|
+
// 'Hello World',和localStorageBTwo中'propB'的双向同步,如果localStorageBTwo中没有'propB',则使用默认值'Hello World'
|
|
719
|
+
@LocalStorageLink('PropB') propB: string = 'Hello World';
|
|
720
|
+
|
|
721
|
+
build() {
|
|
722
|
+
Text(this.propB)
|
|
723
|
+
.fontSize(50)
|
|
724
|
+
.fontWeight(FontWeight.Bold)
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### Navigation组件和LocalStorage联合使用
|
|
730
|
+
|
|
731
|
+
可以通过传递不同的LocalStorage实例给自定义组件,从而实现在[Navigation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation)跳转到不同的页面时,绑定不同的LocalStorage实例,显示对应绑定的值。
|
|
732
|
+
|
|
733
|
+
本示例以@LocalStorageLink为例,展示了:
|
|
734
|
+
|
|
735
|
+
- 点击父组件中的Button "Next Page",创建并跳转到name为"pageOne"的子页面,Text显示信息为LocalStorage实例localStorageA中绑定的propA的值,为"propA"。
|
|
736
|
+
|
|
737
|
+
- 继续点击页面上的Button "Next Page",创建并跳转到name为"pageTwo"的子页面,Text显示信息为LocalStorage实例localStorageB中绑定的propB的值,为"propB"。
|
|
738
|
+
|
|
739
|
+
- 继续点击页面上的Button "Next Page",创建并跳转到name为"pageTree"的子页面,Text显示信息为LocalStorage实例localStorageC中绑定的propC的值,为"propC"。
|
|
740
|
+
|
|
741
|
+
- 继续点击页面上的Button "Next Page",创建并跳转到name为"pageOne"的子页面,Text显示信息为LocalStorage实例localStorageA中绑定的propA的值,为"propA"。
|
|
742
|
+
|
|
743
|
+
- NavigationContentMsgStack自定义组件中的Text组件,共享对应自定义组件树上LocalStorage实例绑定的propA的值。
|
|
744
|
+
|
|
745
|
+
```TypeScript
|
|
746
|
+
let localStorageA: LocalStorage = new LocalStorage();
|
|
747
|
+
localStorageA.setOrCreate('propA', 'propA');
|
|
748
|
+
|
|
749
|
+
let localStorageB: LocalStorage = new LocalStorage();
|
|
750
|
+
localStorageB.setOrCreate('propB', 'propB');
|
|
751
|
+
|
|
752
|
+
let localStorageC: LocalStorage = new LocalStorage();
|
|
753
|
+
localStorageC.setOrCreate('propC', 'propC');
|
|
754
|
+
|
|
755
|
+
@Entry
|
|
756
|
+
@Component
|
|
757
|
+
struct MyNavigationTestStack {
|
|
758
|
+
@Provide('pageInfo') pageInfo: NavPathStack = new NavPathStack();
|
|
759
|
+
|
|
760
|
+
@Builder
|
|
761
|
+
PageMap(name: string) {
|
|
762
|
+
if (name === 'pageOne') {
|
|
763
|
+
// 传递不同的LocalStorage实例
|
|
764
|
+
PageOneStack({}, localStorageA)
|
|
765
|
+
} else if (name === 'pageTwo') {
|
|
766
|
+
PageTwoStack({}, localStorageB)
|
|
767
|
+
} else if (name === 'pageThree') {
|
|
768
|
+
PageThreeStack({}, localStorageC)
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
build() {
|
|
773
|
+
Column({ space: 5 }) {
|
|
774
|
+
Navigation(this.pageInfo) {
|
|
775
|
+
Column() {
|
|
776
|
+
Button('Next Page', { stateEffect: true, type: ButtonType.Capsule })
|
|
777
|
+
.width('80%')
|
|
778
|
+
.height(40)
|
|
779
|
+
.margin(20)
|
|
780
|
+
.onClick(() => {
|
|
781
|
+
this.pageInfo.pushPath({ name: 'pageOne' }); //将name指定的NavDestination页面信息入栈
|
|
782
|
+
})
|
|
783
|
+
}
|
|
784
|
+
}.title('NavIndex')
|
|
785
|
+
.navDestination(this.PageMap)
|
|
786
|
+
.mode(NavigationMode.Stack)
|
|
787
|
+
.borderWidth(1)
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
@Component
|
|
793
|
+
struct PageOneStack {
|
|
794
|
+
@Consume('pageInfo') pageInfo: NavPathStack;
|
|
795
|
+
@LocalStorageLink('PropA') propA: string = 'Hello World';
|
|
796
|
+
|
|
797
|
+
build() {
|
|
798
|
+
NavDestination() {
|
|
799
|
+
Column() {
|
|
800
|
+
NavigationContentMsgStack()
|
|
801
|
+
// 显示绑定的LocalStorage中PropA的值'PropA'
|
|
802
|
+
Text(`${this.propA}`)
|
|
803
|
+
Button('Next Page', { stateEffect: true, type: ButtonType.Capsule })
|
|
804
|
+
.width('80%')
|
|
805
|
+
.height(40)
|
|
806
|
+
.margin(20)
|
|
807
|
+
.onClick(() => {
|
|
808
|
+
this.pageInfo.pushPathByName('pageTwo', null);
|
|
809
|
+
})
|
|
810
|
+
}.width('100%').height('100%')
|
|
811
|
+
}.title('pageOne')
|
|
812
|
+
.onBackPressed(() => {
|
|
813
|
+
this.pageInfo.pop();
|
|
814
|
+
return true;
|
|
815
|
+
})
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
@Component
|
|
820
|
+
struct PageTwoStack {
|
|
821
|
+
@Consume('pageInfo') pageInfo: NavPathStack;
|
|
822
|
+
@LocalStorageLink('PropB') propB: string = 'Hello World';
|
|
823
|
+
|
|
824
|
+
build() {
|
|
825
|
+
NavDestination() {
|
|
826
|
+
Column() {
|
|
827
|
+
NavigationContentMsgStack()
|
|
828
|
+
// 如果绑定的LocalStorage中没有PropB,显示本地初始化的值 'Hello World'
|
|
829
|
+
Text(`${this.propB}`)
|
|
830
|
+
Button('Next Page', { stateEffect: true, type: ButtonType.Capsule })
|
|
831
|
+
.width('80%')
|
|
832
|
+
.height(40)
|
|
833
|
+
.margin(20)
|
|
834
|
+
.onClick(() => {
|
|
835
|
+
this.pageInfo.pushPathByName('pageThree', null);
|
|
836
|
+
})
|
|
837
|
+
|
|
838
|
+
}.width('100%').height('100%')
|
|
839
|
+
}.title('pageTwo')
|
|
840
|
+
.onBackPressed(() => {
|
|
841
|
+
this.pageInfo.pop();
|
|
842
|
+
return true;
|
|
843
|
+
})
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
@Component
|
|
848
|
+
struct PageThreeStack {
|
|
849
|
+
@Consume('pageInfo') pageInfo: NavPathStack;
|
|
850
|
+
@LocalStorageLink('PropC') propC: string = 'pageThreeStack';
|
|
851
|
+
|
|
852
|
+
build() {
|
|
853
|
+
NavDestination() {
|
|
854
|
+
Column() {
|
|
855
|
+
NavigationContentMsgStack()
|
|
856
|
+
|
|
857
|
+
// 如果绑定的LocalStorage中没有PropC,显示本地初始化的值 'pageThreeStack'
|
|
858
|
+
Text(`${this.propC}`)
|
|
859
|
+
Button('Next Page', { stateEffect: true, type: ButtonType.Capsule })
|
|
860
|
+
.width('80%')
|
|
861
|
+
.height(40)
|
|
862
|
+
.margin(20)
|
|
863
|
+
.onClick(() => {
|
|
864
|
+
this.pageInfo.pushPathByName('pageOne', null);
|
|
865
|
+
})
|
|
866
|
+
|
|
867
|
+
}.width('100%').height('100%')
|
|
868
|
+
}.title('pageThree')
|
|
869
|
+
.onBackPressed(() => {
|
|
870
|
+
this.pageInfo.pop();
|
|
871
|
+
return true;
|
|
872
|
+
})
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
@Component
|
|
877
|
+
struct NavigationContentMsgStack {
|
|
878
|
+
@LocalStorageLink('PropA') propA: string = 'Hello';
|
|
879
|
+
|
|
880
|
+
build() {
|
|
881
|
+
Column() {
|
|
882
|
+
Text(`${this.propA}`)
|
|
883
|
+
.fontSize(30)
|
|
884
|
+
.fontWeight(FontWeight.Bold)
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
### LocalStorage支持联合类型
|
|
891
|
+
|
|
892
|
+
在下面的示例中,变量linkA的类型为number | null,变量linkB的类型为number | undefined。Text组件初始化分别显示为null和undefined,点击切换为数字,再次点击切换回null和undefined。
|
|
893
|
+
|
|
894
|
+
```TypeScript
|
|
895
|
+
@Component
|
|
896
|
+
struct LocalStorageLinkComponent {
|
|
897
|
+
@LocalStorageLink('LinkA') linkA: number | null = null;
|
|
898
|
+
@LocalStorageLink('LinkB') linkB: number | undefined = undefined;
|
|
899
|
+
|
|
900
|
+
build() {
|
|
901
|
+
Column() {
|
|
902
|
+
Text('@LocalStorageLink API Initialization, @LocalStorageLink Value')
|
|
903
|
+
Text(`${this.linkA}`)
|
|
904
|
+
.fontSize(20)
|
|
905
|
+
.onClick(() => {
|
|
906
|
+
this.linkA ? this.linkA = null : this.linkA = 1;
|
|
907
|
+
})
|
|
908
|
+
Text(`${this.linkB}`)
|
|
909
|
+
.fontSize(20)
|
|
910
|
+
.onClick(() => {
|
|
911
|
+
this.linkB ? this.linkB = undefined : this.linkB = 1;
|
|
912
|
+
})
|
|
913
|
+
}
|
|
914
|
+
.borderWidth(3).borderColor(Color.Green)
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
@Component
|
|
919
|
+
struct LocalStoragePropComponent {
|
|
920
|
+
@LocalStorageProp('PropA') propA: number | null = null;
|
|
921
|
+
@LocalStorageProp('PropB') propB: number | undefined = undefined;
|
|
922
|
+
|
|
923
|
+
build() {
|
|
924
|
+
Column() {
|
|
925
|
+
Text('@LocalStorageProp API Initialization, @LocalStorageProp Value')
|
|
926
|
+
Text(`${this.propA}`)
|
|
927
|
+
.fontSize(20)
|
|
928
|
+
.onClick(() => {
|
|
929
|
+
this.propA ? this.propA = null : this.propA = 1;
|
|
930
|
+
})
|
|
931
|
+
Text(`${this.propB}`)
|
|
932
|
+
.fontSize(20)
|
|
933
|
+
.onClick(() => {
|
|
934
|
+
this.propB ? this.propB = undefined : this.propB = 1;
|
|
935
|
+
})
|
|
936
|
+
}
|
|
937
|
+
.borderWidth(3)
|
|
938
|
+
.borderColor(Color.Yellow)
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
let storageLink: LocalStorage = new LocalStorage();
|
|
943
|
+
|
|
944
|
+
@Entry(storageLink)
|
|
945
|
+
@Component
|
|
946
|
+
struct LinkIndex {
|
|
947
|
+
build() {
|
|
948
|
+
Row() {
|
|
949
|
+
Column() {
|
|
950
|
+
LocalStorageLinkComponent()
|
|
951
|
+
LocalStoragePropComponent()
|
|
952
|
+
}
|
|
953
|
+
.width('100%')
|
|
954
|
+
}
|
|
955
|
+
.height('100%')
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
### 装饰Array类型变量
|
|
961
|
+
|
|
962
|
+
在下面的示例中,@LocalStorageLink装饰的message类型为number[],点击Button改变message的值,UI会随之刷新。
|
|
963
|
+
|
|
964
|
+
```TypeScript
|
|
965
|
+
@Entry
|
|
966
|
+
@Component
|
|
967
|
+
struct Index {
|
|
968
|
+
@LocalStorageLink('array') message: number[] = [0, 1, 2, 3];
|
|
969
|
+
|
|
970
|
+
build() {
|
|
971
|
+
Column() {
|
|
972
|
+
ForEach(this.message, (item: number) => {
|
|
973
|
+
Text(`${item}`)
|
|
974
|
+
.fontSize(20)
|
|
975
|
+
.margin(10)
|
|
976
|
+
})
|
|
977
|
+
// 新增数组元素,触发UI刷新
|
|
978
|
+
Button('Push element')
|
|
979
|
+
.onClick(() => {
|
|
980
|
+
this.message.push(4);
|
|
981
|
+
})
|
|
982
|
+
.width(300)
|
|
983
|
+
.margin(10)
|
|
984
|
+
// 删除数组元素,触发UI刷新
|
|
985
|
+
Button('Pop element')
|
|
986
|
+
.onClick(() => {
|
|
987
|
+
this.message.pop();
|
|
988
|
+
})
|
|
989
|
+
.width(300)
|
|
990
|
+
.margin(10)
|
|
991
|
+
// 对数组整体重新赋值,触发UI刷新
|
|
992
|
+
Button('Reset array')
|
|
993
|
+
.onClick(() => {
|
|
994
|
+
this.message = [9, 8, 7, 6];
|
|
995
|
+
})
|
|
996
|
+
.width(300)
|
|
997
|
+
.margin(10)
|
|
998
|
+
// 更新数组元素,触发UI刷新
|
|
999
|
+
Button('Modify element[0]')
|
|
1000
|
+
.onClick(() => {
|
|
1001
|
+
this.message[0] = 10;
|
|
1002
|
+
})
|
|
1003
|
+
.width(300)
|
|
1004
|
+
.margin(10)
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
### 装饰Date类型变量
|
|
1011
|
+
|
|
1012
|
+
> **说明:**
|
|
1013
|
+
>
|
|
1014
|
+
> 从API version 12开始,LocalStorage支持Date类型。
|
|
1015
|
+
|
|
1016
|
+
在下面的示例中,@LocalStorageLink装饰的selectedDate类型为Date,点击Button改变selectedDate的值,UI会随之刷新。
|
|
1017
|
+
|
|
1018
|
+
```TypeScript
|
|
1019
|
+
@Entry
|
|
1020
|
+
@Component
|
|
1021
|
+
struct LocalDateSample {
|
|
1022
|
+
@LocalStorageLink('date') selectedDate: Date = new Date('2021-08-08');
|
|
1023
|
+
|
|
1024
|
+
build() {
|
|
1025
|
+
Column() {
|
|
1026
|
+
Button('set selectedDate to 2023-07-08')
|
|
1027
|
+
.margin(10)
|
|
1028
|
+
.onClick(() => {
|
|
1029
|
+
this.selectedDate = new Date('2023-07-08');
|
|
1030
|
+
})
|
|
1031
|
+
Button('increase the year by 1')
|
|
1032
|
+
.margin(10)
|
|
1033
|
+
.onClick(() => {
|
|
1034
|
+
this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1);
|
|
1035
|
+
})
|
|
1036
|
+
Button('increase the month by 1')
|
|
1037
|
+
.margin(10)
|
|
1038
|
+
.onClick(() => {
|
|
1039
|
+
this.selectedDate.setMonth(this.selectedDate.getMonth() + 1);
|
|
1040
|
+
})
|
|
1041
|
+
Button('increase the day by 1')
|
|
1042
|
+
.margin(10)
|
|
1043
|
+
.onClick(() => {
|
|
1044
|
+
this.selectedDate.setDate(this.selectedDate.getDate() + 1);
|
|
1045
|
+
})
|
|
1046
|
+
DatePicker({
|
|
1047
|
+
start: new Date('1970-1-1'),
|
|
1048
|
+
end: new Date('2100-1-1'),
|
|
1049
|
+
selected: $$this.selectedDate
|
|
1050
|
+
})
|
|
1051
|
+
}.width('100%')
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
### 装饰Map类型变量
|
|
1057
|
+
|
|
1058
|
+
> **说明:**
|
|
1059
|
+
>
|
|
1060
|
+
> 从API version 12开始,LocalStorage支持Map类型。
|
|
1061
|
+
|
|
1062
|
+
在下面的示例中,@LocalStorageLink装饰的message类型为Map<number, string>,点击Button改变message的值,UI会随之刷新。
|
|
1063
|
+
|
|
1064
|
+
```TypeScript
|
|
1065
|
+
@Entry
|
|
1066
|
+
@Component
|
|
1067
|
+
struct LocalMapSample {
|
|
1068
|
+
@LocalStorageLink('map') message: Map<number, string> = new Map([[0, 'a'], [1, 'b'], [3, 'c']]);
|
|
1069
|
+
|
|
1070
|
+
build() {
|
|
1071
|
+
Row() {
|
|
1072
|
+
Column() {
|
|
1073
|
+
ForEach(Array.from(this.message.entries()), (item: [number, string]) => {
|
|
1074
|
+
Text(`${item[0]}`).fontSize(30)
|
|
1075
|
+
Text(`${item[1]}`).fontSize(30)
|
|
1076
|
+
Divider()
|
|
1077
|
+
})
|
|
1078
|
+
Button('init map').onClick(() => {
|
|
1079
|
+
this.message = new Map([[0, 'a'], [1, 'b'], [3, 'c']]);
|
|
1080
|
+
})
|
|
1081
|
+
Button('set new one').onClick(() => {
|
|
1082
|
+
this.message.set(4, 'd');
|
|
1083
|
+
})
|
|
1084
|
+
Button('clear').onClick(() => {
|
|
1085
|
+
this.message.clear();
|
|
1086
|
+
})
|
|
1087
|
+
Button('replace the existing one').onClick(() => {
|
|
1088
|
+
this.message.set(0, 'aa');
|
|
1089
|
+
})
|
|
1090
|
+
Button('delete the existing one').onClick(() => {
|
|
1091
|
+
this.message.delete(0);
|
|
1092
|
+
})
|
|
1093
|
+
}
|
|
1094
|
+
.width('100%')
|
|
1095
|
+
}
|
|
1096
|
+
.height('100%')
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
### 装饰Set类型变量
|
|
1102
|
+
|
|
1103
|
+
> **说明:**
|
|
1104
|
+
>
|
|
1105
|
+
> 从API version 12开始,LocalStorage支持Set类型。
|
|
1106
|
+
|
|
1107
|
+
在下面的示例中,@LocalStorageLink装饰的memberSet类型为Set<number>,点击Button改变memberSet的值,UI会随之刷新。
|
|
1108
|
+
|
|
1109
|
+
```TypeScript
|
|
1110
|
+
@Entry
|
|
1111
|
+
@Component
|
|
1112
|
+
struct LocalSetSample {
|
|
1113
|
+
@LocalStorageLink('set') memberSet: Set<number> = new Set([0, 1, 2, 3, 4]);
|
|
1114
|
+
|
|
1115
|
+
build() {
|
|
1116
|
+
Row() {
|
|
1117
|
+
Column() {
|
|
1118
|
+
ForEach(Array.from(this.memberSet.entries()), (item: [number, number]) => {
|
|
1119
|
+
Text(`${item[0]}`)
|
|
1120
|
+
.fontSize(30)
|
|
1121
|
+
Divider()
|
|
1122
|
+
})
|
|
1123
|
+
Button('init set')
|
|
1124
|
+
.onClick(() => {
|
|
1125
|
+
this.memberSet = new Set([0, 1, 2, 3, 4]);
|
|
1126
|
+
})
|
|
1127
|
+
Button('set new one')
|
|
1128
|
+
.onClick(() => {
|
|
1129
|
+
this.memberSet.add(5);
|
|
1130
|
+
})
|
|
1131
|
+
Button('clear')
|
|
1132
|
+
.onClick(() => {
|
|
1133
|
+
this.memberSet.clear();
|
|
1134
|
+
})
|
|
1135
|
+
Button('delete the first one')
|
|
1136
|
+
.onClick(() => {
|
|
1137
|
+
this.memberSet.delete(0);
|
|
1138
|
+
})
|
|
1139
|
+
}
|
|
1140
|
+
.width('100%')
|
|
1141
|
+
}
|
|
1142
|
+
.height('100%')
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
### 自定义组件外改变状态变量
|
|
1148
|
+
|
|
1149
|
+
```TypeScript
|
|
1150
|
+
let storageChange = new LocalStorage();
|
|
1151
|
+
storageChange.setOrCreate('count', 47);
|
|
1152
|
+
|
|
1153
|
+
class Model {
|
|
1154
|
+
public storage: LocalStorage = storageChange;
|
|
1155
|
+
|
|
1156
|
+
call(propName: string, value: number) {
|
|
1157
|
+
this.storage.setOrCreate<number>(propName, value);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
let model: Model = new Model();
|
|
1162
|
+
|
|
1163
|
+
@Entry({ storage: storageChange })
|
|
1164
|
+
@Component
|
|
1165
|
+
struct Test {
|
|
1166
|
+
@LocalStorageLink('count') count: number = 0;
|
|
1167
|
+
|
|
1168
|
+
build() {
|
|
1169
|
+
Column() {
|
|
1170
|
+
Text(`count value: ${this.count}`)
|
|
1171
|
+
Button('change')
|
|
1172
|
+
.onClick(() => {
|
|
1173
|
+
model.call('count', this.count + 1);
|
|
1174
|
+
})
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
```
|