自定义构建函数 #
@Builder #
@Builder
- 组件内
@Builder MyBuilderFunction() {}
this.MyBuilderFunction()
- 全局
@Builder function MyGlobalBuilderFunction() {}
MyGlobalBuilderFunction()
- 参数传递
@Builder MyBuilderFunction( title: string ) {}
this.MyBuilderFunction('Title')
反正就跟自定义控件差不多太多? 使用支持传参使其更加灵活
MyBuilderFunction(params: { title: string }){}
@BuilderParam #
这个简单, 跟compose 差不多太多
@Component
struct PanelComp {
title: string
more: string
@BuilderParam
panelContent: () => void
@BuilderParam
panelFooter: () => void
build() {
Column() {
Row() {
Text(this.title)
.layoutWeight(1)
.fontWeight(600)
Row() {
Text(this.more)
.fontSize(14)
.fontColor('#666666')
Image($r('app.media.ic_public_arrow_right'))
.width(16)
.fillColor('#666666')
}
}
.padding(10)
Row() {
this.panelContent()
}
.height(100)
Row() {
this.panelFooter()
}
.height(50)
}
.borderRadius(12)
.backgroundColor('#fff')
}
}
@Entry
@Component
struct Index {
@Builder
ContentBuilderA() {
Text('评价内容')
}
@Builder
FooterBuilderA() {
Text('评价底部')
}
build() {
Column() {
GridRow({ columns: 2, gutter: 15 }) {
GridCol({ span: 2 }) {
PanelComp({
title: '评价(2000+)',
more: '好评率98%',
panelFooter: this.FooterBuilderA,
panelContent: this.ContentBuilderA
})
}
// GridCol() {
// PanelComp({ title: '推荐', more: '查看全部' }){
// Text('推荐内容')
// }
// }
//
// GridCol() {
// PanelComp({ title: '体验', more: '4 条测评' }){
// Text('体验内容')
// }
// }
}
}
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
状态共享 #
父子单向 #
@Prop
装饰的变量可以和父组件建立单向的同步关系。可变,但是不会传回父组件
@Entry
@Component
struct Index {
@State
money: number = 0
build() {
Column({ space: 20 }){
Text('父组件:' + this.money)
.onClick(() => {
this.money ++
})
Child({ money: this.money })
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}
@Component
struct Child {
@Prop
money: number
build() {
Text('子组件:' + this.money)
.onClick(() => {
this.money ++
})
}
}
注意:
@Prop
支持类型 string、number、boolean、enum
类型
父子共享 #
子组件中被@Link
装饰的变量与其父组件中对应的数据源建立双向数据绑定。
- 简单类型
string number boolean enum
@Entry
@Component
struct Index {
@State
money: number = 0
build() {
Column({ space: 20 }){
Text('父组件:' + this.money)
.onClick(() => {
this.money ++
})
Child({ money: $money })
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}
@Component
struct Child {
@Link
money: number
build() {
Text('子组件:' + this.money)
.onClick(() => {
this.money ++
})
}
}
- 复杂类型
Object class
class Person {
name: string
age: number
}
@Entry
@Component
struct Index {
@State
person: Person = { name: 'jack', age: 18 }
build() {
Column({ space: 20 }){
Text('父组件:' + `${this.person.name} 今年 ${ this.person.age } 岁`)
.onClick(() => {
this.person.age ++
})
Child({ person: $person })
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}
@Component
struct Child {
@Link
person: Person
build() {
Text('子组件:' + `${this.person.name} 今年 ${ this.person.age } 岁`)
.onClick(() => {
this.person.age ++
})
}
}
注意: 父组件传值的时候需要 this.
改成 $
,子组件 @Link
修饰数据
后代组件 #
@Provide
和 @Consume
,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。
- 通过相同的变量名绑定
@Entry
@Component
struct Index {
@Provide
money: number = 0
build() {
Column({ space: 20 }) {
Text('父组件:' + this.money)
.onClick(() => {
this.money++
})
Parent()
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
@Component
struct Parent {
@Consume
money: number
build() {
Column({ space: 20 }) {
Text('父组件:' + this.money)
.onClick(() => {
this.money++
})
Child()
}
}
}
@Component
struct Child {
@Consume
money: number
build() {
Text('子组件:' + this.money)
.onClick(() => {
this.money++
})
}
}
状态监听器 #
如果开发者需要关注某个状态变量的值是否改变,可以使用 @Watch
为状态变量设置回调函数。
@State、@Prop、@Link
等装饰器在@Watch
装饰之前
import promptAction from '@ohos.promptAction'
@Component
struct Child {
@Prop
@Watch('onActiveIndex')
activeIndex: number
onActiveIndex() {
promptAction.showToast({ message: '监听变化' })
}
build() {
Column() {
Text('Child' + this.activeIndex)
}
}
}
@Entry
@Component
struct Index {
@State activeIndex: number = 0
onChange (index: number) {
this.activeIndex = index
promptAction.showToast({ message: '点击' })
}
build() {
Navigation() {
Child({ activeIndex: this.activeIndex })
}.toolBar({
items: [
{ value: '首页', action: () => this.onChange(0) },
{ value: '我的', action: () => this.onChange(1) },
]
})
}
}
tip: 在第一次初始化的时候,@Watch装饰的方法不会被调用
@Observed与@ObjectLink #
修改嵌套对象的数据了更新UI
- 类
class
数据模拟需要定义通过构造函数,使用@Observed
修饰这个类 - 初始化数据:需要通过初始化构造函数的方式添加
- 通过
@ObjectLink
关联对象,可以直接修改被关联对象来更新UI
来看看我自己写的一个沟施例子吧
@Entry
@Component
export default struct Index {
students = [
new Student({
name: "张三",
gender: 1,
age: 12
}),
new Student({
name: "李四",
gender: 1,
age: 13
}),
new Student({
name: "小红",
gender: 0,
age: 13
})
]
build() {
Column() {
ForEach(this.students, (s: Student) => {
Item({s})
})
}
}
}
@Component
struct Item {
@ObjectLink
s: Student
OnLike() {
this.s.age++
}
build() {
Row() {
Text(`姓名: ${this.s.name} 年龄: ${this.s.age}`)
.onClick(() => {
this.OnLike()
})
}.width('100%')
.backgroundColor("#f5f5f5")
.borderRadius(5)
}
}
@Observed
class Student {
gender: number
age: number
name: string
constructor(s: Student) {
for (const key in s) {
this[key] = s[key]
}
}
}
应用状态 #
UIAbility内状态-LocalStorage #
LocalStorage
是页面级的UI状态存储,通过 @Entry
装饰器接收的参数可以在页面内共享同一个 LocalStorage
实例。 LocalStorage
也可以在 UIAbility
内,页面间共享状态。
- 页面内共享
- 创建
LocalStorage
实例:const storage = new LocalStorage({ key: value })
- 单向
@LocalStorageProp('user')
组件内可变 - 双向
@LocalStorageLink('user')
全
class User {
name?: string
age?: number
}
const storage = new LocalStorage({
user: { name: 'jack', age: 18 }
})
@Entry(storage)
@Component
struct Index {
@LocalStorageProp('user')
user: User = {}
build() {
Column({ space: 15 }){
Text('Index:')
Text(this.user.name + this.user.age)
Divider()
ChildA()
Divider()
ChildB()
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
@Component
struct ChildA {
@LocalStorageProp('user')
user: User = {}
build() {
Column({ space: 15 }){
Text('ChildA:')
Text(this.user.name + this.user.age)
.onClick(()=>{
this.user.age ++
})
}
}
}
@Component
struct ChildB {
@LocalStorageLink('user')
user: User = {}
build() {
Column({ space: 15 }){
Text('ChildB:')
Text(this.user.name + this.user.age)
.onClick(()=>{
this.user.age ++
})
}
}
}
- 页面间共享
- 在
UIAbility
创建LocalStorage
通过loadContent
提供给加载的窗口 - 在页面使用
const storage = LocalStorage.GetShared()
得到实例,通过@Entry(storage)
传入页面
entryAbility/EntryAbility.ts
+ storage = new LocalStorage({
+ user: { name: 'jack', age: 18 }
+ })
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+ windowStage.loadContent('pages/Index', this.storage , (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
});
}
models/index.ets
export class User {
name?: string
age?: number
}
pages/Index.ets
import { User } from '../models'
const storage = LocalStorage.GetShared()
@Entry(storage)
@Component
struct Index {
@LocalStorageProp('user')
user: User = {}
build() {
Column({ space: 15 }) {
Text('Index:')
Text(this.user.name + this.user.age)
.onClick(()=>{
this.user.age ++
})
Navigator({ target: 'pages/OtherPage' }){
Text('Go Other Page')
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
pages/OtherPage.ets
import { User } from '../models'
const storage = LocalStorage.GetShared()
@Entry(storage)
@Component
struct OtherPage {
@LocalStorageLink('user')
user: User = {}
build() {
Column({ space: 15 }) {
Text('OtherPage:')
Text(this.user.name + this.user.age)
.onClick(()=>{
this.user.age ++
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
应用状态-AppStorage #
AppStorage
是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
- 如果是初始化使用
AppStorage.SetOrCreate(key,value)
- 单向
@StorageProp('user')
组件内可变 - 双向
@StorageLink('user')
全局均可变
- 通过UI装饰器使用
import { User } from '../models'
AppStorage.SetOrCreate<User>('user', { name: 'jack', age: 18 })
@Entry
@Component
struct Index {
@StorageProp('user')
// 可忽略,编辑器类型错误
user: User = {}
build() {
Column({ space: 15 }) {
Text('Index:')
Text(this.user.name + this.user.age)
.onClick(() => {
this.user.age++
})
Divider()
ChildA()
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
@Component
struct ChildA {
@StorageLink('user')
user: User = {}
build() {
Column({ space: 15 }){
Text('ChildA:')
Text(this.user.name + this.user.age)
.onClick(()=>{
this.user.age ++
})
}
}
}
- 通过逻辑使用
AppStorage.Get<ValueType>(key)
获取数据AppStorage.Set<ValueType>(key,value)
覆盖数据const link: SubscribedAbstractProperty<ValueType> = AppStorage.Link(key)
覆盖数据link.set(value)
修改link.get()
获取
import promptAction from '@ohos.promptAction'
import { User } from '../models'
AppStorage.SetOrCreate<User>('user', { name: 'jack', age: 18 })
@Entry
@Component
struct Index {
@StorageLink('user')
user: User = {}
build() {
Column({ space: 15 }) {
Text('Index:')
Text(this.user.name + this.user.age)
.onClick(() => {
this.user.age++
})
Divider()
Text('Get()')
.onClick(() => {
// 仅获取
const user = AppStorage.Get<User>('user')
promptAction.showToast({
message: JSON.stringify(user)
})
})
Text('Set()')
.onClick(() => {
// 直接设置
AppStorage.Set<User>('user', {
name: 'tom',
age: 100
})
// 观察页面更新没
})
Text('Link()')
.onClick(() => {
// 获取user的prop
const user: SubscribedAbstractProperty<User> = AppStorage.Link('user')
user.set({
name: user.get().name,
// 获取后修改
age: user.get().age + 1
})
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
状态持久化-PersistentStorage #
PersistentStorage
将选定的 AppStorage
属性保留在设备磁盘上。
DETAILS
UI和业务逻辑不直接访问 PersistentStorage
中的属性,所有属性访问都是对 AppStorage
的访问,AppStorage
中的更改会自动同步到 PersistentStorage
。
WARNING
- 支持:number, string, boolean, enum 等简单类型;
- 如果:要支持对象类型,可以转换成json字符串
- 持久化变量最好是小于2kb的数据,如果开发者需要存储大量的数据,建议使用数据库api。
- 简单数据类型的持久化,和获取和修改
import { User } from '../models'
PersistentStorage.PersistProp('count', 100)
@Entry
@Component
struct Index {
@StorageLink('count')
count: number = 0
build() {
Column({ space: 15 }) {
Text(this.count.toString())
.onClick(() => {
this.count++
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
- 复杂数据类型的持久化,和获取和修改
import { User } from '../models'
PersistentStorage.PersistProp('count', 100)
@Entry
@Component
struct Index {
@StorageLink('count')
count: number = 0
build() {
Column({ space: 15 }) {
Text(this.count.toString())
.onClick(() => {
this.count++
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}