HarmonyOS鸿蒙Next中onVisibleAreaChange属性怎么用if else?

HarmonyOS鸿蒙Next中onVisibleAreaChange属性怎么用if else? 在开发埋点功能的时候,旧版系统使用onVisibleAreaChange,有性能劣化。

API 17支持onVisibleAreaApproximateChange

为了兼容旧版系统的用户,需要根据不同用户系统使用不同的接口

普通属性可以在attributeModifier里面进行if else分支

之前发现这两个属性attributeModifier不支持

所以怎么实现呢?

7 回复

思路

由于onVisibleAreaChange和onVisibleAreaApproximateChange属于事件回调而非普通属性,无法直接通过attributeModifier设置。可通过下边的两种方式实现兼容

实现方案

1/条件表达式直接绑定:在组件声明时通过API版本判断选择事件

@Component
struct MyComponent {
  build() {
    Column() {
      // 其他组件内容
    }
    // 根据API版本选择事件
    .onVisibleAreaChange(
      systemVersion >= 17 ? 
        (isVisible: boolean, ratio: number) => {
          // 新API逻辑
          this.handleApproximateChange(ratio);
        } : 
        (isVisible: boolean) => {
          // 旧API逻辑
          this.handleLegacyChange(isVisible);
        }
    )
  }
}

2/生命周期中动态注册:在aboutToAppear生命周期中动态注册事件

@Component
struct MyComponent {
  aboutToAppear() {
    const systemVersion = getContext().config.apiVersion;
    if (systemVersion >= 17) {
      this.registerApproximateEvent();
    } else {
      this.registerLegacyEvent();
    }
  }
  private registerApproximateEvent() {
    this.controller.onVisibleAreaApproximateChange((ratio: number) => {
      // 新版本处理逻辑
    });
  }
  private registerLegacyEvent() {
    this.controller.onVisibleAreaChange((isVisible: boolean) => {
      // 旧版本处理逻辑
    });
  }
}

更多关于HarmonyOS鸿蒙Next中onVisibleAreaChange属性怎么用if else?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


用 AttributeUpdater 来是否可行?

根据鸿蒙文档,onVisibleAreaChangeonVisibleAreaApproximateChange 这两个事件接口是组件的直接方法,并非通过 attributeModifier 设置的属性。因此,无法在 attributeModifierapplyNormalAttribute 等方法中使用 if-else 来动态设置它们。

要实现根据不同API版本(即系统版本)选择使用不同的事件接口,您需要在构建组件时,直接使用条件语句进行判断和调用。

以下是具体实现方法:

解决方案

您可以在构建组件时,使用 ArkTS 的条件渲染或通过判断系统 API 版本来决定调用哪个接口。

步骤 1:获取系统 API 版本

您可以使用 @kit.AbilityKit 中的 getSystemVersion 方法来获取系统的 API 版本。

import { system } from '@kit.AbilityKit';

// 获取系统API版本
let systemVersion: number = system.deviceInfo.sdkApiVersion;

步骤 2:在构建组件时进行条件判断

在组件的 build 方法中,根据获取到的 systemVersion 决定使用哪个事件。

build() {
  Column() {
    YourComponent()
      // 根据系统版本选择不同的事件接口
      .if(systemVersion >= 17, ()=>{
        // API 17+ 使用高性能接口
        this.onVisibleAreaApproximateChange([0.5], (isExpanding: boolean, currentRatio: number) => {
          // 你的曝光埋点逻辑
          console.log(`Approximate Change: isExpanding=${isExpanding}, ratio=${currentRatio}`);
        })
      })
      .else(()=> {
        // API 9-16 使用原始接口
        this.onVisibleAreaChange([0.5], (isExpanding: boolean, currentRatio: number) => {
          // 你的曝光埋点逻辑
          console.log(`Change: isExpanding=${isExpanding}, ratio=${currentRatio}`);
        })
      })
  }
}

或者,更常见的写法是使用三元表达式或 if 语句来返回不同的组件链:

build() {
  Column() {
    // 先创建公共的组件
    let component = YourComponent();
    
    // 然后根据条件为其添加不同的事件
    if (systemVersion >= 17) {
      component = component.onVisibleAreaApproximateChange([0.5], (isExpanding: boolean, currentRatio: number) => {
        // 回调逻辑
      });
    } else {
      component = component.onVisibleAreaChange([0.5], (isExpanding: boolean, currentRatio: number) => {
        // 回调逻辑
      });
    }
    
    // 最后将构建好的组件放入布局中
    component
  }
}

重要说明

  1. 性能考量:您的判断非常正确。onVisibleAreaChange 在每帧都会进行计算,如果页面中注册此事件的节点过多,会显著增加系统负载和功耗。而 onVisibleAreaApproximateChange (API 17+) 通过 expectedUpdateInterval 参数降低了计算频率,是为解决多组件监听场景的性能问题而设计的。因此,对旧版系统用户需要承担此性能风险,或考虑在旧版系统上减少监听组件的数量。

  2. attributeModifier 的用途attributeModifier 主要用于动态修改组件的样式属性(如背景色、大小等)或通用事件(如 onClick),它并不适用于动态设置组件生命周期相关的特殊事件回调(如 onVisibleAreaChange)。

总结

特性 onVisibleAreaChange (API 9+) onVisibleAreaApproximateChange (API 17+)
计算频率 每帧计算,精度高,功耗大 可控制间隔,计算频率低,性能优
适用场景 少量需要精准感知可见性变化的组件 大量组件(如列表项曝光统计)
默认阈值 默认包含 0 阈值

为了实现兼容,您应该在构建组件时通过判断 system.deviceInfo.sdkApiVersion 来动态调用不同的接口,而不是在 attributeModifier 中操作。这是处理此类因系统版本不同而使用不同API的标准方法。

Ai没调教好,

现在鸿蒙next都是api17+的设备了吧,其实不做兼容也行吧,还是你在做开源鸿蒙的项目需要兼容api17-的设备,

在HarmonyOS鸿蒙Next中,onVisibleAreaChange是组件可见性变化时的回调函数。可通过判断visibleRatio属性实现条件逻辑。示例:

onVisibleAreaChange((isVisible, visibleRatio) => {
  if (visibleRatio > 0.5) {
    // 组件超过50%可见时执行
  } else {
    // 组件可见度低于50%时执行
  }
})

visibleRatio表示组件在可视区域的占比,范围0-1。通过比较该值与设定阈值,即可实现if-else条件判断。

在HarmonyOS Next中,onVisibleAreaChangeonVisibleAreaApproximateChange是组件属性,无法直接在attributeModifier中使用条件分支。建议通过以下方式实现兼容:

  1. 使用条件编译或运行时API版本判断:通过system.version获取系统版本,在组件构建时动态选择属性。例如:
if (system.version >= 17) {
  component.onVisibleAreaApproximateChange(...);
} else {
  component.onVisibleAreaChange(...);
}
  1. 封装自定义组件:将版本判断逻辑封装到高阶组件或自定义组件中,根据API级别动态绑定对应属性。

这样可以避免性能问题,同时保持对旧版本的兼容性。

回到顶部