上一节我们介绍了同一颗组件树上单层级关系组件也就是父子关系组件之间的状态管理(@Prop/@Link),那么如果是跨层级的组件之间又应该如何传递状态呢?诚然我们可以通过@Prop或者@Link一层层地传递下去:
但其实我们有更加简便的方法,那就是使用@Provide和@Consume装饰器配合。从字面意义来理解,前者是“提供",后者是“消费",也就是前者装饰的变量是提供给后者装饰的变量去消费的。@Provide装饰的变量是在祖先组件中,@Consume装饰的变量是在后代组件中,且必须给@Consume提供数据源变量的名称作为参数:
这样一来我们就把后代组件Widget中的selected变量和祖先组件Index中的allSelected关联起来了,而不需要通过ContactListItem组件去中转。注意,使用@Provide和@Consume装饰器关联的变量是双向绑定的。
现在我们来指出并解决另一个问题,目前为止我们已经学习过的关于状态管理的装饰器,无论是@State还是@Provide还是@Watch,当它们装饰的是自定义类型的数组或者嵌套自定义类型时,被装饰的状态变量的可观测性只有一层,我们来测试一下。
我们发现预览器中的界面并没有发生变化,联系人列表的第一项名称依然为“大熊”:
**要想让状态变量的第二层被观测到,我们需要使用@Observed装饰器配合@Prop或者@ObjectLink装饰器。@Observed装饰器只能用于装饰类(class),不能用于装饰接口,因此,我们需要重新定义一个联系人信息类CContact,并把Index页面和ContantListItem中所有用到IContactInfo的地方都改成CContactInfo。注意被@Observed装饰的类必须用new创建该类的对象,才能被观测到第二层的变化:
**
现在,我们再点击按钮修改熊大,就会发现熊大的名字能够正确地变成大雄了:
目前我们所学的状态管理都是单个页面中组件间传递状态的,那么如果我们想在多个页面中传递状态呢?这就轮到LocalStorage出场了。LocalStorage既可以在单个页面的不同组件中传递状态,也可以在多个页面中传递状态,但是由于LocalStorage在多个页面传递状态时需要用到的GetShared()方法无法在预览器中生效,所以接下来我们先来学习如何使用模拟器调试我们的项目。点击导航栏右侧的设备选择框,选择Device Manager:
弹出来的协议窗口直接点Agree:
下载可用的新镜像:
点击第一项Huawei_Phone后面的下载按钮:
同意协议并下一步,开始下载镜像:
下载完成后点击Finish:
回到设备选择界面点击Next,开始配置虚拟机,16G以上的机器保持默认即可,8G的机器可以把运存调到3GB。配置好后点击Finish:
我们就会看见设备创建成功的提示了。点击OK关掉提示窗,然后点击我们刚刚创建的设备后面的启动按钮:
等待片刻虚拟机设备就会启动成功,现在可以关掉设备管理界面了:
可以看到设备选择栏里面已经自动更改为我们刚刚启动的设备。我们点击右侧的运行按钮,稍等片刻项目就会运行到我们的虚拟机设备中了:
如果我们点击的不是运行按钮而是运行按钮右侧的调试按钮,项目同样也会运行到虚拟机中,且支持断点调试:
如果我们想要用真机调试,首先需要登录华为开发者账号。点击右上角的个人中心图标,点击Sign in登录账号:
在跳转的登录页面中登自己的华为账号(如果没有账号需要先注册):
允许让DevEco访问你的华为账号:
网页出现以下提示就是登录成功了,DevEco的通知中心也会提示:
把我们的鸿蒙Next真机用数据线连接到电脑(或者通过主菜单栏Tools-IP Connection进行无线连接,需要设备打开无线调试开关),此时设备选择栏的列表中就会出现我们的真机名称:
选择该设备,然后点击运行按钮,右下角会出现未设置签名的提示:
**点击主菜单栏的File-Project Structure,打开项目结构窗口,选择Project选项卡的Signing Configs标签页,等待片刻就会自动生成调试签名文件:
**
点击OK按钮,调试签名就配置好了。现在我们再次点击项目的运行按钮,稍等片刻项目就可以运行到我们的真机上了:
我们点击真机上的返回按钮,可以看到我们的项目图标和名称都是默认的icon和“label”,正式项目的话我们肯定是需要修改的:
从项目浏览窗口里面找到entry/src/main/module.json5文件并打开,我们要修改的内容就在里面:
点击“label"配置项的值label,会发现它实际定位的是string资源中的EntryAbility_label资源,我们按住Ctrl键然后点击"$string:EntryAbility_label"字样,跳转到string资源的配置页(会有三个选择,如果不做国际化应用,选择zh_CN目录下的即可):
修改EntryAbility_label配置项的值,保存然后重新运行项目,我们可以发现应用的名称已经改变了(如果出现没变化的情况,请真机上卸载旧的App再重新点击运行项目):
icon的修改也是差不多的流程,只要把icon资源放进media资源目录,然后在module.json5中替换就可以了:
现在我们可以接着讲LocalStorage了。LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。LocalStorage在一个应用中可以创建多个,但每个页面最多只能分配一个。根据使用范围的不同,它有两种使用方式,我们新建一个项目LocalStorageDemo来学习:
- 页面内共享 LocalStorage对象创建在页面代码文件中,并在@Entry装饰器的参数中直接装载。这种方式只能在本页面中共享该storage,页面中的所有组件自动获得对该storage的访问权,我们既可以通过@LocalStorageProp或者@LocalStorageLink装饰器来让成员变量链接该storage中的数据,也可以直接用程序逻辑的方式来获取或操作该storage中的数据:
- 页面间共享 LocalStorage对象创建在UIAbility代码中,使用WindowsStage.loadContent()时作为第二个参数,并在启动页通过getShared()方法获取LocalStorage的实例后再传给@Entry作为参数装载:
这种方式支持加载LocalStorage实例的页面能跳转到的所有页面共享该LocalStorage,但需要注意的是仅支持Navigation方式的跳转,对router方式的跳转则不支持!所以下一节我们学习之前忽略的Navigation跳转方式。