东莞正规网站建设,如何编写一份网站开发需求文档,wordpress 简书模板,湖南昌正建设有限公司网站一、基础UI组件结构 每个UI组件需要定义为Component struct对象#xff0c;其内部必须包含一个且只能包含一个build(){}函数#xff0c;用于绘制UI#xff1b;struct之内、build()函数之外的地方用于存放数据。
二、基本UI装饰器
Entry
装饰struct#xff0c;页面的入口…一、基础UI组件结构 每个UI组件需要定义为Component struct对象其内部必须包含一个且只能包含一个build(){}函数用于绘制UIstruct之内、build()函数之外的地方用于存放数据。
二、基本UI装饰器
Entry
装饰struct页面的入口
Component
装饰struct表示该struct具有基于组件的能力
Entry
Component
struct TestPage {build() {……}
}
三、数据装饰器
State 父子相互独立
装饰的变量是组件的局部变量必须本地初始化可通过构造参数赋值当该数据被修改时所在组件的build()方法会被重新调用会重新绘制所在UI
子组价
Component
export struct ComponentPage {State count: number 0private toggleClick() {this.count 1}build() {Row() {Column({ space: 20 }) {Button(这是子组件${this.count}).fontSize(24).onClick(this.toggleClick.bind(this))}.width(100%)}}
}
父组件
import { ComponentPage } from ./ComponentPageEntry
Component
struct StatePage {State count: number 0private toggleClick() {this.count 1}build() {Row() {Column({ space: 20 }) {Button(这是父组件当前值: ${this.count}).fontSize(24).onClick(this.toggleClick.bind(this))//使用默认初始化值ComponentPage()//设置count初始值为20ComponentPage({ count: 20 })}.width(100%)}.height(100%)}
}
描述
当被点击之后修改了count的值页面会重新绘制UI子组件中的count和父组件的count互不影响可以给子组件构造方法设置初始值使用State修饰的变量必须初始化
效果图 Prop 父子单向同步
继承State的所有功能被其装饰的变量可以和父组件建立单向同步关系。Prop装饰的变量是可变的但修改不会同步回父组件当父组件的State变化时本地修改的Prop会被覆盖
子组件
Component
export struct ComponentPage {Prop count: numberprivate toggleClick() {this.count 1}build() {Row() {Column({ space: 20 }) {Button(这是子组件${this.count}).fontSize(24).onClick(this.toggleClick.bind(this))}.width(100%)}}
}
父组件
import { ComponentPage } from ./ComponentPageEntry
Component
struct StatePage {State count: number 0private toggleClick() {this.count 1}build() {Row() {Column({ space: 20 }) {Button(这是父组件当前值: ${this.count}).fontSize(24).onClick(this.toggleClick.bind(this))ComponentPage({ count: this.count })}.width(100%)}.height(100%)}
}
描述
将父组件的count设置到子组件使用的Prop修饰的变量时父组件与子组件这时建立起单向同步父组件修改值后子组件跟着修改子组件修改值父组件不受影响使用的Prop修饰的变量不能自己初始化
效果图 Link 父子双向同步
Link装饰的变量和父组件构建双向同步关系的状态变量父组件会接受来自Link装饰的变量的修改的同步父组件的更新也会同步给Link装饰的变量。Link装饰的变量与其父组件中的数据源共享相同的值Link装饰器不能在Entry装饰的自定义组件中使用
子组件
Component
export struct ComponentPage {Link count: numberprivate toggleClick() {this.count 1}build() {Row() {Column({ space: 20 }) {Button(这是子组件${this.count}).fontSize(24).onClick(this.toggleClick.bind(this))}.width(100%)}}
}
父组件
import { ComponentPage } from ./ComponentPageEntry
Component
struct StatePage {State count: number 0private toggleClick() {this.count 1}build() {Row() {Column({ space: 20 }) {Button(这是父组件当前值: ${this.count}).fontSize(24).onClick(this.toggleClick.bind(this))ComponentPage({ count: $count })}.width(100%)}.height(100%)}
}
描述
父组件通过$count来和子组件的Link修饰的值绑定绑定之后实现父子双向绑定修改一端另一组件也随之变化使用Link不能自己初始化
效果图 State、Prop与Link的异同
相同点
都会引起UI重绘内部私有
不同点
不同点StatePropLink装饰内容基本数据类型类数组基本数据类型基本数据类型类数组关联不与其他控件关联父State - 子Prop 单向关联父State - 子Link 双向关联初始化时机声明时创建组件时由参数传入创建组件时由参数传入
四、生产消费的装饰器
Provide、Consume
后代通过使用Consume去获取Provide提供的变量建立在Provide和Consume之间的双向数据同步与State/Link不同的是前者可以在多层级的父子组件之间传递
案例
在父组件中将数据多级传递给子组件子子组件
1.使用Link修饰的变量进行传递
父组件
import { ProviderSonPage } from ./ProviderSonPageEntry
Component
struct ProviderPage {State message: string 父类Abuild() {Row() {Column() {Text(this.message).fontSize(50).fontColor(Color.Red).onClick(() {//点击文字 进行切换this.message this.message 父类A ? 父类B : 父类A})//调用子组件ProviderSonPage({ sonMsg: $message })}.width(100%)}.height(100%)}
}
子组件
import { ProviderGrandSonPage } from ./ProviderGrandSonPageComponent
export struct ProviderSonPage {Link sonMsg: stringbuild() {Column() {Text(this.sonMsg).fontSize(30).fontColor(Color.Green).onClick(() {this.sonMsg 我是子类})//调用孙子组件子类的子类ProviderGrandSonPage({ grandSonMsg: $sonMsg })}}
}
子子组件
Component
export struct ProviderGrandSonPage {Link grandSonMsg: stringbuild() {Column() {Text(this.grandSonMsg).fontSize(20).fontColor(Color.Blue).onClick(() {this.grandSonMsg 我是子类的子类})}}
}
总结
都需要通过一个多余被Link修饰的变量进行传递太过复杂如果传递层级太深没更加明显
2.发布者订阅者模式
使用发布者Provide和订阅者Consume可以直接传递到子子组件
父组件
import { ProviderSonPage } from ./ProviderSonPageEntry
Component
struct ProviderPage {Provide(Mes) message: string 父类A//也可以写成Provide message: string 父类Abuild() {Row() {Column() {Text(this.message).fontSize(50).fontColor(Color.Red).onClick(() {this.message this.message 父类A ? 父类B : 父类A})//调用子组件时就不再需要传递参数ProviderSonPage()}.width(100%)}.height(100%)}
}
子组件
import { ProviderGrandSonPage } from ./ProviderGrandSonPageComponent
export struct ProviderSonPage {Consume(Mes) sonMsg:stringbuild() {Column() {Text(this.sonMsg).fontSize(30).fontColor(Color.Green).onClick(() {this.sonMsg 我是子类})//调用子组件时就不再需要传递参数ProviderGrandSonPage()}}
}
子子组件
Component
export struct ProviderGrandSonPage {Consume(Mes) grandSonMsg:string//也可以写成Consume message:stringbuild() {Column() {Text(this.grandSonMsg).fontSize(20).fontColor(Color.Blue).onClick(() {this.grandSonMsg 我是子类的子类})}}
}
总结
使用发布者订阅者模式父类使用Provide其他需要观察的子类使用Consume就可以能实现双向绑定当层级很深时不需要一层一层的往下传递直接使用发布者订阅者进行监听就能实现相同的效果Provide和Consume可以通过相同的变量名或者相同的变量别名绑定变量类型必须相同Provide必须设置初始值Consume不可设置默认初始值Provide修饰的变量和Consume修饰的变量是一对多的关系
效果图 五、状态变量更改通知
Watch使用观察者模式的装饰器但该装饰器不是触发变量变化而是绑定一个函数当Watch变量变化时调用该函数
Watch和自定义组件更新
子组件
Component
export struct TotalViewPage {Prop Watch(onCountUpdated) count: number;State total: number 0;// Watch 回调onCountUpdated(propName: string): void {this.total this.count;}build() {Text(Total: ${this.total})}
}
父组件
import {TotalViewPage} from ./TotalViewPageEntry
Component
struct CountModifierPage {State count: number 0;build() {Column() {Button(add to basket).onClick(() {this.count})TotalViewPage({ count: this.count })}}
}
描述
CountModifier自定义组件的Button.onClick点击事件自增count由于State count变量更改子组件TotalView中的Prop被更新其Watch(onCountUpdated)方法被调用更新了子组件TotalView 中的total变量子组件TotalView中的Text重新渲染
Watch与Link组合使用
bean对象PurchaseItem
export class PurchaseItem {static NextId: number 0;public id: number;public price: number;constructor(price: number) {this.id PurchaseItem.NextId;this.price price;}
}
子类BasketViewer
import {PurchaseItem} from ./PurchaseItemComponent
export struct BasketViewer {Link Watch(onBasketUpdated) shopBasket: PurchaseItem[];State totalPurchase: number 0;updateTotal(): number {let total this.shopBasket.reduce((sum, i) sum i.price, 0);// 超过100欧元可享受折扣if (total 100) {total 0.9 * total;}return total;}// Watch 回调onBasketUpdated(propName: string): void {this.totalPurchase this.updateTotal();}build() {Column() {ForEach(this.shopBasket,(item) {Text(Price: ${item.price.toFixed(2)} €)},item item.id.toString())Text(Total: ${this.totalPurchase.toFixed(2)} €)}}
}
父类BasketModifierPage
import {BasketViewer} from ./BasketViewer
import {PurchaseItem} from ./PurchaseItemEntry
Component
struct BasketModifierPage {State shopBasket: PurchaseItem[] [];build() {Column() {Button(Add to basket).onClick(() {this.shopBasket.push(new PurchaseItem(Math.round(100 * Math.random())))})BasketViewer({ shopBasket: $shopBasket })}}
}描述
BasketModifierPage组件的Button.onClick向BasketModifier shopBasket中添加条目Link装饰的BasketViewer shopBasket值发生变化状态管理框架调用Watch函数BasketViewer onBasketUpdated 更新BasketViewer TotalPurchase的值Link shopBasket的改变新增了数组项ForEach组件会执行item Builder渲染构建新的Item项State totalPurchase改变对应的Text组件也重新渲染重新渲染是异步发生的