HarmonyOS 鸿蒙Next:传入的 Prop 已修改且 UI 层已更改,但在 promise 中无法获取最新值,应如何处理?

HarmonyOS 鸿蒙Next:传入的 Prop 已修改且 UI 层已更改,但在 promise 中无法获取最新值,应如何处理? 现象如下:

  • 目前首次点击,弹出提示框文案为:【父组件初始值】
    • 我的期望是弹出【改值了!!!】
  • 后续再进行点击没问题的,因为此时 msg 确实已经变为【改值了!!!】

排查及猜想:

  • 首次点击与期望不符合,猜想可能有类似于 nextTick 之类的东西,应当等待子组件的 Prop 更新了之后,再去执行 showToast 。
  • 看了一圈也没有找到符合的 API。难道真的要用 setTimeout 这种方式去延迟 showToast 吗?😭
  • 尝试了用 setTimeout 延迟去 showToast,最后发现只有 10ms 以上,才能达到期望结果;

各位大佬帮忙看看这个代码该如何修改,或者说是换一种写法?

原始代码如下(代码文案贴在最后方便粘贴):

cke_2603.gif

import { promptAction } from '@kit.ArkUI';

@Component
struct Child {
  @Prop msg: string = "原始数据"
  cb: () => Promise<void> = () => {
    return Promise.resolve()
  }

  build() {
    Button(this.msg).onClick(() => {
      this.cb().then(() => {
        console.log("from Child", this.msg)
        setTimeout(() => {
          promptAction.showToast({ message: this.msg })
        }, 10)
      })
    })
  }
}

@Entry
@Component
struct Parent {
  @State msg: string = "父组件初始值"
  parentFunc = () => {
    const pFunc: Promise<void> = new Promise((resolve: Function) => {
      this.msg = "改值了!!!"
      console.log("from Parent", this.msg)
      resolve()
    })
    return pFunc
  }

  build() {
    Column() {
      Child({
        msg: this.msg,
        cb: this.parentFunc
      })
    }
  }
}

更多关于HarmonyOS 鸿蒙Next:传入的 Prop 已修改且 UI 层已更改,但在 promise 中无法获取最新值,应如何处理?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

11 回复

总结原因:

@Prop本身就是深拷贝,同步数据时不是和Link一样同步更新,当同步父组件数据时,需要走组件更新函数,也就是会晚于父组件一帧的时间进行标脏,那么他刷新的时间就需要两帧。

@Link只需要当前帧标脏,下一帧刷新;

更多关于HarmonyOS 鸿蒙Next:传入的 Prop 已修改且 UI 层已更改,但在 promise 中无法获取最新值,应如何处理?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


@Link 应该来说是最佳方案了,感谢解答🙏,

也可以用@Watch来监控@Prop来实现,参考:

import { promptAction } from '@kit.ArkUI';

@Component
struct Child {
  [@Prop](/user/Prop) [@Watch](/user/Watch)('chlTest') msg: string = "原始数据"
  cb: () => Promise<void> = () => {
    return Promise.resolve()
  }

  chlTest(propName: string): void {
    console.log("from Child", this.msg)
    promptAction.showToast({ message: this.msg })
  }

  build() {
    Button(this.msg).onClick(() => {
      this.cb().then(() => {
      
      })
    })
  }
}

@Entry
@Component
struct Parent {
  @State msg: string = "父组件初始值"
  parentFunc = () => {
    const pFunc: Promise<void> = new Promise((resolve: Function) => {
      this.msg = "改值了!!!"
      console.log("from Parent", this.msg)
      resolve()
    })
    return pFunc
  }

  build() {
    Column() {
      Child({
        msg: this.msg,
        cb: this.parentFunc
      })
    }
  }
}
 showToast会执行两遍吧这样?

只会执行一遍,

Child 中的这个函数没有执行,所以只执行了一遍。按理来说应该在 Promise.then 结束后再去执行 showToast 的,所以这行代码应当是去执行的;

Button(this.msg).onClick(() => { this.cb().then(() => { // 你给的示例中没有执行 this.chlTest this.chlTest() }) }),

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

1、可以用@Provide来做:

import { promptAction } from '@kit.ArkUI';

@Component
struct Child {
  @Consume("pMsg") msg: string
  cb: () => Promise<void> = () => {
    return Promise.resolve()
  }

  build() {
    Button(this.msg).onClick(() => {
      this.cb().then(() => {
        console.log("from Child", this.msg)
        promptAction.showToast({ message: this.msg })
      })
    })
  }
}

@Entry
@Component
struct Parent {
  [@Provide](/user/Provide)("pMsg") msg: string = "父组件初始值"
  parentFunc = () => {
    const pFunc: Promise<void> = new Promise((resolve: Function) => {
      this.msg = "改值了!!!"
      console.log("from Parent", this.msg)
      resolve()
    })
    return pFunc
  }

  build() {
    Column() {
      Child({
        cb: this.parentFunc
      })
    }
  }
}

2、 把@Prop改成@Link也可以

请问大佬还有别的方案吗?

  • 使用 @Provide 会影响所有子组件,并不打算污染其他子孙组件。
  • 使用 @Link 双向绑定没有必要,子组件不需要修改 msg 的值。

也可以用@Watch来监控@Prop

在HarmonyOS鸿蒙Next中,如果传入的Prop已修改且UI层已更改,但在Promise中无法获取最新值,这通常是因为数据绑定和异步处理的时机问题。以下是一些可能的处理方法:

  1. 确保数据绑定正确:首先,检查你的数据绑定是否正确设置。在鸿蒙系统中,通常使用双向数据绑定来确保UI与数据源的同步。确保你的Prop和UI元素正确绑定,且数据源在修改后能够触发UI的更新。

  2. 使用回调函数或监听器:当Prop值改变时,可以通过回调函数或监听器来捕获这一变化。在Promise执行完毕后,通过调用这些回调或监听器来获取最新的Prop值。

  3. 异步处理与数据更新的顺序:确保你的异步操作(如Promise)在数据更新之后执行。可以通过将异步操作放在数据更新事件的回调函数中来实现这一点。

  4. 使用全局状态管理:如果数据在多个组件或页面间共享,考虑使用全局状态管理(如鸿蒙的GlobalContext)来确保数据的一致性。

  5. 检查Promise的使用方式:确保Promise的使用方式正确,没有导致数据访问的时机错误。例如,避免在Promise链中错误地捕获或处理数据。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部