HarmonyOS 鸿蒙Next 为什么这个 tabs 在测试中点击切换会很卡?几秒后才能出现,有的时候甚至不出现

发布于 1周前 作者 vueper 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 为什么这个 tabs 在测试中点击切换会很卡?几秒后才能出现,有的时候甚至不出现

import WaterFlowList from ‘…/home/WaterFlowList’

@Component
export default struct tabs {
@State currentIndex: number = 0

@Builder
TabBarBuilder(title: ResourceStr, index: number) {
Text(title)
.fontSize(14)
.fontWeight(‘600’)
.fontColor(index == this.currentIndex ? ‘#fff’ : ‘#888’)
.backgroundColor(index == this.currentIndex ? ‘#0175F9’ : ‘#fafafa’)
.borderRadius(5)
.width(‘80%’)
.textAlign(TextAlign.Center)
.height(‘26’)
}

build() {

Tabs() {
TabContent() {
Text(‘发布’)
}
.tabBar(this.TabBarBuilder(‘发布’, 0))

TabContent() {
Text(‘收藏’)
}
.tabBar(this.TabBarBuilder(‘收藏’, 1))

TabContent() {
Text(‘喜欢’)
}
.tabBar(this.TabBarBuilder(‘喜欢’, 2))

TabContent() {
Text(‘打卡地’)
}
.tabBar(this.TabBarBuilder(‘打卡地’, 3))

TabContent() {
Text(‘喜欢’)
}
.tabBar(this.TabBarBuilder(‘喜欢’, 4))

TabContent() {
Text(‘打卡地’)
}
.tabBar(this.TabBarBuilder(‘打卡地’, 5))

}
.width(‘100%’)
.margin({ top: 2, bottom: 2 })
.barHeight(‘35’)
.barWidth(‘100%’)
// .height(‘280%’)
.backgroundColor(’#f3f3f3’)
.barBackgroundColor(’#fff’)

.borderRadius(0)
.animationDuration(0) //animationDuration为0关闭动画
.scrollable(true)
//设置为true时可以通过滑动页面进行页面切换,为false时不可滑动切换页面。
//
// 默认值:true
.onChange((index: number) => {
this.currentIndex = index
})
}
}

13 回复

吐槽下你这个代码颜色,说回正题,可能是TabContent 内容过于复杂或重渲染,没有使用懒加载机制,给你改进了下:

[@Component](/user/Component)  
struct TabContentItem {  
 [@Prop](/user/Prop) title: string  
 
 build() {  
   Column() {  
     Text(this.title)  
       .fontSize(16)  
       .fontWeight(500)  
   }  
   .width('100%')  
   .height('100%')  
   .justifyContent(FlexAlign.Center)  
   .alignItems(HorizontalAlign.Center)  
 }  
}  

[@Component](/user/Component)  
export default struct OptimizedTabs {  
 [@State](/user/State) currentIndex: number = 0  
 private tabTitles: string[] = ['发布', '收藏', '喜欢', '打卡地', '历史', '推荐']  

 [@Builder](/user/Builder)  
 TabBarBuilder(title: string, index: number) {  
   Text(title)  
     .fontSize(14)  
     .fontWeight(FontWeight.Medium)  
     .fontColor(index === this.currentIndex ? '#FFFFFF' : '#888888')  
     .backgroundColor(index === this.currentIndex ? '#0175F9' : '#FAFAFA')  
     .borderRadius(5)  
     .width('80%')  
     .textAlign(TextAlign.Center)  
     .height(26)  
     .padding({ left: 10, right: 10 })  
 }  

 build() {  
   Tabs({ barPosition: BarPosition.Top }) {  
     ForEach(this.tabTitles, (title: string, index: number) => {  
       TabContent() {  
         TabContentItem({ title: title })  
       }  
       .tabBar(this.TabBarBuilder(title, index))  
     }, (title: string) => title)  
   }  
   .width('100%')  
   .margin({ top: 2, bottom: 2 })  
   .barHeight(35)  
   .backgroundColor('#F3F3F3')  
   .barBackgroundColor('#FFFFFF')  
   .borderRadius(0)  
   .animationDuration(200)  // 适当的动画时长  
   .scrollable(true)  
   .onChange((index: number) => {  
     this.currentIndex = index  
   })  
 }  
}

大神 问一下 为什么要给那么长的 动画时长呢 ?

用你的方法 确实会好很多,但是依旧存在点击没反应 导致无法切换的 感觉是随机的 没有规律 ,

但是 在我另外一个项目 就切换自如,是不是组件之间相互切换导致的 加载慢 哎

import SiteLine from ‘…/Site/SiteList’ import MineAddList from ‘…/mine/MineAddList’

@Component export default struct tabs { @State currentIndex: number = 0

@Builder TabBarBuilder(title: ResourceStr, index: number) { Text(title) .fontSize(14) .fontWeight(‘600’) .fontColor(index == this.currentIndex ? ‘#fff’ : ‘#888’) .backgroundColor(index == this.currentIndex ? ‘#0175F9’ : ‘#fff’) .borderRadius(5) .width(‘80%’) .textAlign(TextAlign.Center) .height(‘26’) }

build() {

Tabs() {
  TabContent() {
    MineAddList()
  }
  .tabBar(this.TabBarBuilder('发布', 0))

  TabContent() {
    MineAddList()
  }
  .tabBar(this.TabBarBuilder('收藏', 1))

  TabContent() {
    MineAddList()
  }
  .tabBar(this.TabBarBuilder('喜欢', 2))

  TabContent() {
    SiteLine()
  }
  .tabBar(this.TabBarBuilder('打卡地', 3))


}
.width('100%')
.margin({ top: 0, bottom: 0 })
.barHeight('46')
.barWidth('98%')
// .height('280%')
.backgroundColor('#f3f3f3')

.borderRadius(20)
.animationDuration(0) //animationDuration为0关闭动画
.scrollable(true)
//设置为true时可以通过滑动页面进行页面切换,为false时不可滑动切换页面。
//
// 默认值:true


.onChange((index: number) => {
  this.currentIndex = index
})

} }

你可以自己设置,我只是给了一个明显的动画效果

我再给你写一个优化后的,也有可能是你项目开发初期存在的一些暗病,这里没办法看到:
[@Component](/user/Component)  
struct TabContentItem {  
  [@Prop](/user/Prop) title: string  

build() {
Column() {
Text(this.title)
.fontSize(16)
.fontWeight(FontWeight.Medium)
}
.width(‘100%’)
.height(‘100%’)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}

@Component
export default struct OptimizedTabs {
@State private currentIndex: number = 0
@State private isChanging: boolean = false
private tabTitles: string[] = [‘发布’, ‘收藏’, ‘喜欢’, ‘打卡地’, ‘历史’, ‘推荐’]
private lastClickTime: number = 0
private CLICK_DEBOUNCE_TIME: number = 300 // 防抖时间 300ms

@Builder
TabBarBuilder(title: string, index: number) {
Text(title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor(index === this.currentIndex ? ‘#FFFFFF’ : ‘#888888’)
.backgroundColor(index === this.currentIndex ? ‘#0175F9’ : ‘#FAFAFA’)
.borderRadius(5)
.width(‘80%’)
.textAlign(TextAlign.Center)
.height(26)
.padding({ left: 10, right: 10 })
.onClick(() => this.safeChangeTab(index))
}

// 安全的Tab切换方法 private safeChangeTab(index: number) {
const currentTime = new Date().getTime()

<span class="hljs-comment">// 防抖处理  </span>
<span class="hljs-keyword">if</span> (currentTime - <span class="hljs-keyword">this</span>.lastClickTime &lt; <span class="hljs-keyword">this</span>.CLICK_DEBOUNCE_TIME) {  
  <span class="hljs-keyword">return</span>  
}  

<span class="hljs-comment">// 防止重复点击  </span>
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.isChanging || index === <span class="hljs-keyword">this</span>.currentIndex) {  
  <span class="hljs-keyword">return</span>  
}  

<span class="hljs-keyword">this</span>.lastClickTime = currentTime  
<span class="hljs-keyword">this</span>.isChanging = <span class="hljs-literal">true</span>  

<span class="hljs-comment">// 异步更新,避免阻塞  </span>
setTimeout(() =&gt; {  
  <span class="hljs-keyword">this</span>.currentIndex = index  
  <span class="hljs-keyword">this</span>.isChanging = <span class="hljs-literal">false</span>  
}, <span class="hljs-number">50</span>)  

}

build() {
Tabs({
barPosition: BarPosition.Top,
index: this.currentIndex
}) {
ForEach(this.tabTitles, (title: string, index: number) => {
TabContent() {
TabContentItem({ title: title })
}
.tabBar(this.TabBarBuilder(title, index))
}, (title: string) => title)
}
.width(‘100%’)
.margin({ top: 2, bottom: 2 })
.barHeight(35)
.backgroundColor(’#F3F3F3’)
.barBackgroundColor(’#FFFFFF’)
.borderRadius(0)
.animationDuration(200)
.scrollable(true)
.onChange((index: number) => {
if (!this.isChanging) {
this.currentIndex = index
}
})
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>


 

把TabContent单拎出来成一个组件好点

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

onChange改变currentIndex的时候会等动画结束的时候赋值,有动画效果;

onTabBarClick即刻改变currentIndex,不会触发动画直接触发。

不知道你的具体代码写法,我这个没看到有卡顿。


[@Entry](/user/Entry)
[@Component](/user/Component)
export default struct OptimizedTabs {
  [@State](/user/State) currentIndex: number = 0
  private tabTitles: string[] = ['发布', '收藏', '喜欢', '打卡地', '历史', '推荐']

private controller: TabsController = new TabsController()

@Builder TabBarBuilder(title: string, index: number) { Text(title) .fontSize(14) .fontWeight(FontWeight.Medium) .fontColor(index === this.currentIndex ? ‘#FFFFFF’ : ‘#888888’) .backgroundColor(index === this.currentIndex ? ‘#0175F9’ : ‘#FAFAFA’) .borderRadius(5) .width(‘120%’) .textAlign(TextAlign.Center) .height(26) .padding({ left: 10, right: 10 }) }

// controller: this.controller build() { Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) { ForEach(this.tabTitles, (title: string, index: number) => { TabContent() { TabContentItem({ title: title, index: index }) } .backgroundColor(index % 2 === 1 ? Color.Gray : Color.Orange) .tabBar(this.TabBarBuilder(title, index)) }, (title: string) => title) } .width(‘100%’) .height(‘100%’) .margin({ top: 2, bottom: 2 }) .barHeight(35) .backgroundColor(’#F3F3F3’) .barBackgroundColor(’#FFFFFF’) .borderRadius(0) .onTabBarClick((index: number) => { // currentIndex控制TabContent显示页签 this.currentIndex = index }) } }

@Component struct TabContentItem { @Prop title: string @Prop index: number

build() { Scroll() { Column(){ ForEach([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,2,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,2], (item: number) => { Text(this.title) .lineHeight(40) .fontSize(20) .fontWeight(500) }, (item: number, index: number) => item.toString() + index.toString()) } .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) } .width(‘100%’) // .backgroundColor(Color.Blue) .initialOffset({ yOffset: this.index % 2 === 1 ? ‘1000%’ : ‘100%’ }) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

是指tabBar在切花不同样式时有延迟吗,还是什么问题,onChange本就会有一定延迟,建议通过参数双向绑定
 Tabs({index: $$this.selectIndex })<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

在切换 tab 的时候 卡 你的方法我已经绑定了 延迟 好几秒 才能切换的动

会不会是硬件原因,因为你这代码也不复杂

我把你这代码放在页面里没问题,看你是导出形式,找别的原因吧,组件没问题

针对HarmonyOS 鸿蒙Next中Tabs组件在测试中点击切换卡顿的问题,这通常是由于多种因素导致的。以下是一些可能的原因及解决方案:

  1. 性能问题:确保应用及系统资源充足,减少不必要的后台进程和服务,以提升系统响应速度。
  2. 动画效果:Tabs组件默认的切换动画可能会带来一定的延迟。可以尝试通过设置Tabs组件的animationDuration属性为0,关闭切换动画,以减少延迟。
  3. 数据加载:Tabs切换时需要加载指定item,涉及组件创建、数据解析和初始化等操作。可以考虑预加载指定item,但需要注意性能影响,建议分批加载子节点。

如果上述方法仍然无法解决Tabs切换卡顿的问题,可能是由于系统或应用存在其他潜在问题。此时,建议联系官网客服,以获取更专业的技术支持。官网地址是:https://www.itying.com/category-93-b0.html

回到顶部