--写在前面
在鸿蒙 Next 应用开发的领域中,稍微大丢丢的项目都会用到传值问题,虽然component组件不算鸿蒙意义上的页面,但我们从眼观上来讲,也是一种“页面”。甚至我们现在正在赶进度的项目,技术老大一直在强调少注册页面,尽可能的使用组件套用,路由方面使用navcation哈哈,这个路由我们后面再聊。
传值四大类:1-装饰器变量传值 2-数据库类 3-首选项4-Emitter传值。我们一一来看
--装饰器变量传值(暂不考虑V2)
@state --@Link 双向父子
@state --@Prop 单向父子
@Provide--@Consume 关系树
@Observed--@ObjectLink 用到的数据需要有@Observed 修饰他们的数据所在类--UI可观测深层次的值变化
--储存数据传值
---LocalStorage 页面级UI变量储存
实现跨页面、UIAbility实例内共享-退出app后消失
用法
创建实例
let storage = new LocalStorage({ 'PropA': 47 }); // 创建新实例并使用给定对象初始化
//----2开始用,get(key) link(key) prop(key)
let propA = storage.get('PropA') // propA == 47
let link1 = storage.link('PropA'); // link1.get() == 47
let link2 = storage.link('PropA'); // link2.get() == 47
let prop = storage.prop('PropA'); // prop.get() = 47
//---3-改变----区别点:用实例后赋值的变量 .set() 不用加key-
link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48
prop.set(1); // one-way sync: prop.get()=1; but link1.get() == link2.get() == 48
link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49
@LocalStorageLink(key) ---和页面级的UI状态存储LocalStorage页面级的UI状态存储 双向 ==通过 @Entry 装饰器接收的参数可以在页面内共享同一个--页面互传可在某个页面改动储存-再在使用页面重新导入储存
@LocalStorageProp(key) ---和缓存页面级的UI状态存储LocalStorage; 单向 ==通过 @Entry 装饰器接收的参数可以在状态储存单向传给UIAbility内所有页面
在UI中的用法
//1-- 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });
@Component
struct Child {
//3- @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
@LocalStorageLink('PropA') storLink2: number = 1;
build() {
Button(`Child from LocalStorage ${this.storLink2}`)
// 更改将同步至LocalStorage中的'PropA'以及Parent.storLink1
.onClick(() => this.storLink2 += 1)
}
}
// 2-使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct CompA {
// 3--用@LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
@LocalStorageLink('PropA') storLink1: number = 1;
build() {
Column({ space: 15 }) {
Button(`Parent from LocalStorage ${this.storLink1}`) // initial value from LocalStorage will be 47, because 'PropA' initialized already
//需要改变的时候赋值就是改动
.onClick(() => this.storLink1 += 1)
// @Component子组件自动获得对CompA LocalStorage实例的访问权限。
Child()
}
}
}
@StorageLink(key) ---和缓存AppStorage区域 双向
用法: AppStorage.setOrCreate('user', { name: 'jack', age: 18 })
使用: 在struct 下面
@StorageLink('user')
user: User = {
name: '',
age: 0
}
--Emmiter页面间传值-不储存
即时传递数据-接收方提前注册好接收事件emmiter.on(放在abouttoAppear里就好,提前注册,随时接收传来的id信号) 传递源在有值的时候传出-emmiter.emmit
这里要注意在子组件出现的emmiter注册事件要保证其先被注册,才会被执行,一对emmiter传递中,注册永远走在传递签名。
---用法形式1,id为唯一字符串
emitter.on注册
//接收上传头像传来的imgkey-一般上传逻辑都是异步,想要将结果及时拿到-可用emmiter也可以做临时应用缓存或持久化
emitter.on('imgkey', (EventData) => {
this.imgKey = (EventData.data as IEmitterModel).key
this.tempuri = (EventData.data as IEmitterModel).uri
})
emitter.emit传递
//传递方
let eventData = {
data: {
key: res.key,
hash: res.hash,
uri: uri
} as IEmitterModel //想要传数据-提前订好类型
} as emitter.EventData
// 发送eventId为touxiang的事件,事件内容为eventData-传递给头像修改页面
emitter.emit('imgkey', eventData)
---用法形式2,id为唯一数字
emitter.on注册
注册-//注意这里id的写法与上面不同,都对,但2种写法不能交叉用哦
aboutToAppear(): void {
emitter.on({ eventId: 99 }, (data) => {
this.friendPhone = (data.data as phoneModel).phoneNumber
console.log(`selectContact callback: success data2->${this.friendPhone}`)
})
}
emitter.emit传递
//拿到数据再传给用到的地方
emitter.emit({eventId: 99, priority: emitter.EventPriority.LOW },
{ data: { phoneNumber: phoneNum }
})
在这里要注意emitter传递数据是要一个类或一个interface这适合新手,不过要额外去定义一个类型,如果传的是简单几个字段,可以实现这个中括号取值方式
emitter.on({ eventId: 99 }, (data) => {
this.imgNanSign = (data.data as object)['url']
})
emitter.emit({eventId: 99, priority: emitter.EventPriority.LOW }, { data: { url: url } })})
那么还有一种方式,如果你对Record<T,T>这个数据类型的使用比较熟悉的话,也是很不错的,这个可以节约一个定义类型,那么在这里如何使用呢?期待你的评论
如果看到这里,不妨点个赞加个关注哦,嘿嘿,就很棒