状况同享-父子单向
**@Prop** 装修的变量能够和父组件建立单向的同步联系。**@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 ++
})
}
}
- 支撑类型 string、number、boolean、enum 类型
- 子组件可修正 Prop 数据值,但不同步到父组件,父组件更新后覆盖子组件 Prop 数据
- 子组件能够初始化默认值,留意:目前编译器会提示错误,请疏忽,下个版别将修正
状况同享-父子双向
子组件中被@Link装修的变量与其父组件中对应的数据源建立双向数据绑定。
1)简略类型 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 ++
})
}
}
2)复杂类型 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 修饰数据
3. 状况同享-子孙组件
@Provide 和 @Consume,应用于与子孙组件的双向数据同步,应用于状况数据在多个层级之间传递的场景。
1)经过相同的变量名绑定
@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++
})
}
}
Object、class、string、number、boolean、enum 类型均支撑
经过相同的变量别号绑定 @Provide(‘key’) 和 @Consume(‘key’) key需求保持一致
4. 状况同享-状况监听器
如果开发者需求关注某个状况变量的值是否改变,能够运用 @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) },
]
})
}
}
- 在第一次初始化的时分,@Watch装修的办法不会被调用
5. @Observed与@ObjectLink
之前咱们经过 赋值的方法 修正嵌套目标或目标数组这类复杂数据来更新UI,会影响目标对应一切UI更新; 经过 @Observed 与 @ObjectLink 能够优化这个问题;
运用过程:
-
类 class 数据模拟需求界说经过结构函数,运用 @Observed 修饰这个类
-
初始化数据:需求经过初始化结构函数的方法增加
-
经过 @ObjectLink 相关目标,能够直接修正被相关目标来更新UI
需求:改造下知乎谈论案例
1)界说结构函数和运用@Observed 修饰符,以及初始化数据
models/index.ets
@Observed
export class ReplyItem {
id: number
avatar: string | Resource
author: string
content: string
time: string
area: string
likeNum: number
likeFlag?: boolean
constructor(item: ReplyItem) {
for (const key in item) {
this[key] = item[key]
}
}
}
export const replyList: ReplyItem[] = [
new ReplyItem({
id: 1,
avatar: 'https://www.6hu.cc/storage/2024/02/236124-Sr44E3.jpg?source=06d4cd63',
author: '偏执狂-妄想家',
content: '更何况还分到一个摩洛哥[惊喜]',
time: '11-30',
area: '海南',
likeNum: 34
}),
new ReplyItem({
id: 2,
avatar: 'https://www.6hu.cc/storage/2024/02/236124-xbSGDR.jpg?source=32738c0c',
author: 'William',
content: '当年希腊但是把1:0发挥到极致了',
time: '11-29',
area: '北京',
likeNum: 58
}),
new ReplyItem({
id: 3,
avatar: 'https://www.6hu.cc/storage/2024/02/236124-RXmpZ5.jpg?source=06d4cd63',
author: 'Andy Garcia',
content: '欧洲杯其实16队球队打正赛已经差不多,24队打正赛意味着正赛阶段在小组赛相同有弱队。',
time: '11-28',
area: '上海',
likeNum: 10
}),
new ReplyItem({
id: 4,
avatar: 'https://www.6hu.cc/storage/2024/02/236124-g1VsgZ.jpg?source=06d4cd63',
author: '正宗好鱼头',
content: '的确眼红啊,亚洲就没这种球队,让中国队刷',
time: '11-27',
area: '香港',
likeNum: 139
}),
new ReplyItem({
id: 5,
avatar: 'https://www.6hu.cc/storage/2024/02/236124-7u4cgx.jpg?source=06d4cd63',
author: '柱子哥',
content: '我是支撑扩展的,亚洲杯欧洲杯扩到32队,世界杯扩到64队才是好的,世界上有超越200支部队,欧洲区55支部队,亚洲区47支部队,即使如此也就六成呈现率',
time: '11-27',
area: '旧金山',
likeNum: 29
}),
new ReplyItem({
id: 6,
avatar: 'https://www.6hu.cc/storage/2024/02/236124-Q8hIFQ.jpg?source=06d4cd63',
author: '飞轩逸',
content: '制止欧洲杯扩军之前,应该先制止世界杯扩军,或许至少把亚洲名额一半给欧洲。',
time: '11-26',
area: '里约',
likeNum: 100
})
]
2)嵌套的目标,或许数组中的目标,传入子组件,组件运用 @ObjectLink 修饰符获取数据
pages/Index.ets
import promptAction from '@ohos.promptAction'
import { ReplyItem, replyList } from '../models'
@Entry
@Component
struct Index {
@State
replyList: ReplyItem[] = replyList
@State
content: string = ''
onReply() {
const reply: ReplyItem = new ReplyItem({
id: Math.random(),
content: this.content,
author: 'Zhousg',
avatar: $r('app.media.avatar'),
time: '12-01',
likeNum: 0,
area: '北京'
})
this.replyList.unshift(reply)
this.content = ''
promptAction.showToast({ message: '回复成功' })
}
build() {
Stack() {
Scroll() {
Column() {
NavComp()
CommentComp()
// space
Divider()
.strokeWidth(8)
.color('#f5f5f5')
// reply
Column() {
Text('回复 7')
.width('100%')
.margin({ bottom: 15 })
.fontWeight(500)
ForEach(this.replyList, (item: ReplyItem) => {
ReplyComp({ item })
})
}
.padding({ left: 15, right: 15, top: 15 })
}
}
.padding({ bottom: 50 })
Row() {
TextInput({ placeholder: '回复~', text: this.content })
.placeholderColor('#c3c4c5')
.layoutWeight(1)
.onChange((value) => {
this.content = value
})
Text('发布')
.fontSize(14)
.fontColor('#09f')
.margin({ left: 15 })
.onClick(() => {
this.onReply()
})
}
.width('100%')
.height(50)
.padding({ left: 15, right: 15 })
.position({ y: '100%' })
.translate({ y: -50 })
.backgroundColor('#fff')
.border({ width: { top: 0.5 }, color: '#e4e4e4' })
}
}
}
@Component
struct ReplyComp {
@ObjectLink
item: ReplyItem
onLike() {
if (this.item.likeFlag) {
this.item.likeNum--
this.item.likeFlag = false
promptAction.showToast({ message: '取消点赞' })
} else {
this.item.likeNum++
this.item.likeFlag = true
promptAction.showToast({ message: '点赞成功' })
}
}
build() {
Row() {
Image(this.item.avatar)
.width(32)
.height(32)
.borderRadius(16)
Column() {
Text(this.item.author)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
Text(this.item.content)
.margin({ bottom: 5 })
.fontColor('#565656')
.lineHeight(20)
Row() {
Text(`${this.item.time}•IP 属地${this.item.area}`)
.layoutWeight(1)
.fontSize(14)
.fontColor('#c3c4c5')
Row() {
Image($r('app.media.heart'))
.width(14)
.height(14)
.fillColor(this.item.likeFlag ? '#ff6600' : '#c3c4c5')
.margin({ right: 4 })
Text(this.item.likeNum.toString())
.fontSize(14)
.fontColor(this.item.likeFlag ? '#ff6600' : '#c3c4c5')
}
.onClick(() => {
this.onLike()
})
}
}
.layoutWeight(1)
.padding({ left: 10 })
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding({ bottom: 15 })
.alignItems(VerticalAlign.Top)
}
}
@Component
struct NavComp {
build() {
// nav
Row() {
Row() {
Image($r('app.media.ic_public_arrow_left'))
.width(12)
.height(12)
.fillColor('#848484')
}
.width(24)
.height(24)
.borderRadius(12)
.backgroundColor('#f5f5f5')
.justifyContent(FlexAlign.Center)
.margin({ left: 13 })
Text('谈论回复')
.padding({ right: 50 })
.textAlign(TextAlign.Center)
.fontSize(18)
.layoutWeight(1)
}
.height(50)
}
}
@Component
struct CommentComp {
build() {
// comment
Row() {
Image('https://www.6hu.cc/storage/2024/02/236124-EyhPdV.jpg?source=c885d018')
.width(32)
.height(32)
.borderRadius(16)
Column() {
Text('欧洲足球锦标赛')
.fontSize(15)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
Text('14-0!欧洲杯超级惨案+刷爆纪录!姆巴佩帽子戏法,法国7连胜,怎么点评这场竞赛?')
.margin({ bottom: 5 })
.fontColor('#565656')
.lineHeight(20)
Row() {
Text('10-21•IP 属地辽宁')
.layoutWeight(1)
.fontSize(14)
.fontColor('#c3c4c5')
Row() {
Image($r('app.media.heart'))
.width(14)
.height(14)
.fillColor('#c3c4c5')
.margin({ right: 4 })
Text('100')
.fontSize(14)
.fontColor('#c3c4c5')
}
}
}
.layoutWeight(1)
.padding({ left: 10 })
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding({ left: 15, right: 15, bottom: 15 })
.alignItems(VerticalAlign.Top)
}
}
留意:
-
目标需求经过结构函数初始化
-
需求嵌套组件,因为需求运用 @ObjectLink
关注公众号:Android老皮!!!欢迎大家来找我讨论沟通