鸿蒙NEXT开发浅进阶到精通07:开发实战中常用页面传值方式,emitter是最终大招吗

140 阅读4分钟

--写在前面

在鸿蒙 Next 应用开发的领域中,稍微大丢丢的项目都会用到传值问题,虽然component组件不算鸿蒙意义上的页面,但我们从眼观上来讲,也是一种“页面”。甚至我们现在正在赶进度的项目,技术老大一直在强调少注册页面,尽可能的使用组件套用,路由方面使用navcation哈哈,这个路由我们后面再聊。

传值四大类:1-装饰器变量传值 2-数据库类 3-首选项4-Emitter传值。我们一一来看

--装饰器变量传值(暂不考虑V2)

@state --@Link 双向父子

@state --@Prop 单向父子

@Provide--@Consume 关系树

@Observed--@ObjectLink 用到的数据需要有@Observed 修饰他们的数据所在类--UI可观测深层次的值变化

--储存数据传值

---LocalStorage 页面级UI变量储存

实现跨页面、UIAbility实例内共享-退出app后消失

用法

image.png

创建实例
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()
    }
  }
}

管理应用拥有的状态-状态管理-学习ArkTS语言-入门

@StorageLink(key) ---和缓存AppStorage区域 双向

用法: AppStorage.setOrCreate('user', { name: 'jack', age: 18 })

使用: 在struct 下面

@StorageLink('user')

user: User = {

name: '',

age: 0

}

image.png

--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>这个数据类型的使用比较熟悉的话,也是很不错的,这个可以节约一个定义类型,那么在这里如何使用呢?期待你的评论

如果看到这里,不妨点个赞加个关注哦,嘿嘿,就很棒