seo优化代运营,wordpress站群怎么优化,wordpress分布式,响应式网站模板百度云HarmonyOS#xff08;八#xff09;管理组件状态
概述
在应用中#xff0c;界面通常都是动态的。如图1所示#xff0c;在子目标列表中#xff0c;当用户点击目标一#xff0c;目标一会呈现展开状态#xff0c;再次点击目标一#xff0c;目标一呈现收起状态。界面会根…HarmonyOS八管理组件状态
概述
在应用中界面通常都是动态的。如图1所示在子目标列表中当用户点击目标一目标一会呈现展开状态再次点击目标一目标一呈现收起状态。界面会根据不同的状态展示不一样的效果。
图1 展开/收起目标项
ArkUI作为一种声明式UI具有状态驱动UI更新的特点。当用户进行界面交互或有外部事件引起状态改变时状态的变化会触发组件自动更新。所以在ArkUI中我们只需要通过一个变量来记录状态。当改变状态的时候ArkUI就会自动更新界面中受影响的部分。 ArkUI框架提供了多种管理状态的装饰器来修饰变量使用这些装饰器修饰的变量即称为状态变量。
在组件范围传递的状态管理常见的场景如下
场景装饰器组件内的状态管理State从父组件单向同步状态Prop与父组件双向同步状态Link跨组件层级双向同步状态Provide和Consume
在组件内使用State装饰器来修饰变量可以使组件根据不同的状态来呈现不同的效果。若当前组件的状态需要通过其父组件传递而来此时需要使用Prop装饰器若是父子组件状态需要相互绑定进行双向同步则需要使用Link装饰器。使用Provide和Consume装饰器可以实现跨组件层级双向同步状态。
在实际应用开发中应用会根据需要封装数据模型。如果需要观察嵌套类对象属性变化需要使用Observed和ObjectLink装饰器因为上述表格中的装饰器只能观察到对象的第一层属性变化。Observed和ObjectLink装饰器的具体使用方法可参考Observed装饰器和ObjectLink装饰器嵌套类对象属性变化。
另外当状态改变需要对状态变化进行监听做一些相应的操作时可以使用Watch装饰器来修饰状态。
组件内的状态管理State
实际开发中由于交互组件的内容呈现可能产生变化。当需要在组件内使用状态来控制UI的不同呈现方式时可以使用State装饰器。以任务管理应用为例当点击子目标列表的其中一项列表项会展开。当再次点击同一项列表项会收起。所以对于某一个列表项来说它的呈现方式会受列表项是否展开这个状态影响。
图2 展开/收起目标项
将是否展开这个状态定义为isExpanded变量当其值为false表示目标项收起值为true时表示目标项展开。
此时需要使用State装饰器修饰isExpanded使其成为目标项内部的状态变量。通过State装饰后框架内部会建立数据与视图间的绑定
当isExpanded状态变化时目标项会随之展开或收起。
图3 定义是否展开状态
其具体实现只要用State修饰isExpanded变量定义是否展开状态。然后通过条件渲染实现是否显示进度调整面板和列表项的高度变化。最后监听列表项的点击事件在onClick回调中改变isExpanded状态。
这样就实现了对相同列表项点击时列表项的展开和收起功能。当用户反复点击同一个列表项时组件内的isExpanded状态变化列表项会自动更新。
Component
export default struct TargetListItem {State isExpanded: boolean false;...build() {...Column() {...if (this.isExpanded) {Blank()ProgressEditPanel(...)}}.height(this.isExpanded ? $r(app.float.expanded_item_height) : $r(app.float.list_item_height)).onClick(() {...this.isExpanded !this.isExpanded;...})...}
}从父组件单向同步状态Prop
当子组件中的状态依赖从父组件传递而来时需要使用Prop装饰器Prop修饰的变量可以和其父组件中的状态建立单向同步关系。当父组件中状态变化时该状态值也会更新至Prop修饰的变量对Prop修饰的变量的修改不会影响其父组件中的状态。
图4 列表的编辑模式
如图4所示在目标管理应用中当用户点击子目标列表的“编辑”文本列表进入编辑模式点击取消列表退出编辑模式。
整个列表是自定义组件TargetList顶部是文本显示区域主要是Text组件底部是一个Button组件。中间区域则是用来显示每个目标项目标项是自定义组件TargetListItem。
从图中可以看出TargetListItem是TargetList的子组件。TargetList是TargetListItem父组件。
图5 TargetList和TargetListItem
对于父组件TargetList其顶部显示的文本和底部按钮会随编辑模式的变化而变化因此父组件拥有编辑模式状态。
对于子组件TargetListItem其最右侧是否预留位置和显示勾选框也会随编辑模式变化因此子组件也拥有编辑模式状态。
但是是否进入编辑模式其触发点是在用户点击列表的“编辑”或取消按钮状态变化的源头仅在于父组件TargetList。当父组件TargetList中的编辑模式变化时子组件TargetListItem的编辑模式状态需要随之变化。
图6 从父组件单向同步isEditMode状态
在父组件TargetList中可以定义一个是否进入编辑模式的状态即用State修饰isEditMode。State修饰的变量不仅是组件内部的状态也可以作为子组件单向或双向同步的数据源。ArkUI提供了Prop装饰器Prop修饰的变量可以和其父组件中的状态建立单向同步关系所以用Prop修饰子组件TargetListItem中的isEditMode变量。
在父组件TargetList中用State修饰isEditMode定义编辑模式状态。然后利用条件渲染实现根据是否进入编辑模式显示不同的文本和按钮。同时在父组件中需要在用户点击时改变状态触发界面更新。
当点击“编辑”事件发生时进入编辑模式显示取消、全选文本和勾选框同时显示删除按钮当点击“取消”事件发生时退出编辑模式显示“编辑”文本和“添加子目标”按钮。
Component
export default struct TargetList {State isEditMode: boolean false;...build() {Column() {Row() {...if (this.isEditMode) {Text($r(app.string.cancel_button)).onClick(() {this.isEditMode false;...})...Text($r(app.string.select_all_button))...Checkbox()...} else {Text($r(app.string.edit_button)).onClick(() {this.isEditMode true;})...}...}...List({ space: CommonConstants.LIST_SPACE }) {ForEach(this.targetData, (item: TaskItemBean, index: number) {ListItem() {TargetListItem({isEditMode: this.isEditMode,...})}}, (item, index) JSON.stringify(item) index)}...if (this.isEditMode) {Button($r(app.string.delete_button))} else {Button($r(app.string.add_task))}}...}
}在子组件TargetListItem中使用Prop修饰子组件的isEditMode变量定义子组件的编辑模式状态。然后同样根据是否进入编辑模式控制目标项最右侧是否预留位置和显示勾选框。
Component
export default struct TargetListItem {Prop isEditMode: boolean;...Column() {...}.padding({...right: this.isEditMode ? $r(app.float.list_edit_padding) : $r(app.float.list_padding)})...if (this.isEditMode) {Row() {Checkbox()...}}...
}最后最关键的一步就是要在父组件中使用子组件时将父组件的编辑模式状态this.isEditMode传递给子组件的编辑模式状态isEditMode。
Component
export default struct TargetList {State isEditMode: boolean false;...build() {Column() {...List({ space: CommonConstants.LIST_SPACE }) {ForEach(this.targetData, (item: TaskItemBean, index: number) {ListItem() {TargetListItem({isEditMode: this.isEditMode,...})}}, (item, index) JSON.stringify(item) index)}...}...}
}与父组件双向同步状态Link
若是父子组件状态需要相互绑定进行双向同步时可以使用Link装饰器。父组件中用于初始化子组件Link变量的必须是在父组件中定义的状态变量。
图7 切换目标项
在目标管理应用中当用户点击同一个目标目标项会展开或者收起。当用户点击不同的目标项时除了被点击的目标项展开同时前一次被点击的目标项会收起。
如图7所示当目标一展开时点击目标三目标三会展开同时目标一会收起。再点击目标一时目标一展开同时目标三会收起。
从目标一切换到目标三的流程中关键在于最后目标一的收起当点击目标三时目标一需要知道点击了目标三目标一才会收起。
图8 子目标列表目标项位置索引
在子目标列表中每个列表项都有其位置索引值index属性表示目标项在列表中的位置。index从0开始即第一个目标项的索引值为0第二个目标项的索引值为1以此类推。此外clickIndex用来记录被点击的目标项索引。当点击目标一时clickIndex为0点击目标三时clickIndex为2。
在父组件子目标列表和每个子组件目标项中都拥有clickIndex状态。当目标一展开时clickIndex为0。此时点击目标三目标三的clickIndex变为2只要其父组件子目标列表感知到clickIndex状态变化同时将此变化传递给目标一。目标一的clickIndex即可同步改变为2即目标一感知到此时点击了目标三。
图9 与父组件双向同步clickIndex状态
将列表和目标项对应到列表组件TargetList和列表项TargetListItem。首先需要在父组件TargetList中定义clickIndex状态。
若此时子组件中的clickIndex用Prop装饰器修饰当子组件中clickIndex变化时父组件无法感知因为Prop装饰器建立的是从父组件到子组件的单向同步关系。
ArkUI提供了Link装饰器用于与父组件双向同步状态。当子组件TargetListItem中的clickIndex用Link修饰可与父组件TargetList中的clickIndex建立双向同步关系。
Component
export default struct TargetList {State clickIndex: number CommonConstants.DEFAULT_CLICK_INDEX;...TargetListItem({clickIndex: $clickIndex,...})...
}首先在父组件TargetList中用State装饰器定义点击的目标项索引状态。然后在子组件TargetListItem中用Link装饰器定义clickIndex当点击目标项时clickIndex更新为当前目标索引值。
完成在父子组件中定义状态后最关键的就是要建立父子组件的双向关联关系。在父组件中使用子组件时将父组件的clickIndex传递给子组件的clickIndex。其中父组件的clickIndex加上$表示传递的是引用。
Component
export default struct TargetListItem {Link Watch(onClickIndexChanged) clickIndex: number;State isExpanded: boolean false...onClickIndexChanged() {if (this.clickIndex ! this.index) {this.isExpanded false;}}build() {...Column() {...}.onClick(() {...this.clickIndex this.index;...})...}
}当目标一感知到点击了目标三时还需要将目标一收起切换列表项的功能才是完整的。此时目标一感知到clickIndex变为2需要判断与目标一本身的位置索引值0不相等从而将目标一收起。此时就需要用到ArkUI中监听状态变化Watch的能力。用Watch修饰的状态当状态发生变化时会触发声明时定义的回调。
我们给TargetListItem的中的clickIndex状态加上Watch(“onClickIndexChanged”)。这表示需要监听clickIndex状态的变化。当clickIndex状态变化时将触发onClickIndexChanged回调如果点击的列表项索引不等于当前列表项索引则将isExpanded状态置为false从而收起该目标项。
跨组件层级双向同步状态Provide和Consume 跨组件层级双向同步状态是指Provide修饰的状态变量自动对提供者组件的所有后代组件可用后代组件通过使用Consume装饰的变量来获得对提供的状态变量的访问。Provide作为数据的提供方可以更新其子孙节点的数据并触发页面渲染。Consume在感知到Provide数据的更新后会触发当前自定义组件的重新渲染。
使用Provide的好处是开发者不需要多次将变量在组件间传递。Provide和Consume的具体使用方法请参见开发指南Provide装饰器和Consume装饰器与后代组件双向同步。
参考
更多状态管理场景和相关知识请参考开发指南状态管理。