HarmonyOS 鸿蒙Next中Navigation路由导航失败闪退

HarmonyOS 鸿蒙Next中Navigation路由导航失败闪退 我在一个主页面里通过选项卡创建了三个菜单选项。

假设这个主页叫 tablayout.ets

然后在第一个 tab 选项里导入其他组件来显示内容,假设这个文件叫 home.ets

home.ets 里创建了 list 内容,现在我希望通过点击列表的内容跳转到另一个详情页面 details.ets,目前通过

this.pathStack.replacePathByName('Details',"")

在模拟器里应用会直接闪退,报错的日志如下:

Device info:emulator
Build info:emulator 5.0.1.120(SP3DEVC00E120R4P11log)
Fingerprint:8009285a5bd4047a2bf5f85b6e7aa4de20e0674baf363b2b4808cb917798fd63
Module name:com.example.goldsingle
Version:1.0.0
VersionCode:1000000
PreInstalled:No
Foreground:Yes
Pid:23530
Uid:20020052
Reason:TypeError
Error name:TypeError
Error message:is not callable
Stacktrace:
    at anonymous (entry/src/main/ets/pages/Home.ets:262:17)

layout.ets 大致内容:

import { Calculate } from "./calculate"
import { Home } from "./Home"
import { Settings } from "./settings"

interface TabClass {
  text:string
  // icon:ResourceStr
}

// 跳转页面入口函数,是页面与路由框架的桥梁,确保导航时能正确地加载和管理页面。
@Builder
export function LayoutBuilder() {
  Layout()
}

@ComponentV2
struct Layout {
  @Local currentIndex:number = 0

  // 控制跳转的对象
  pathStack:NavPathStack = new NavPathStack()

  tabData:TabClass[] = [
    {text:"主页"},
    {text:'计算'},
    {text:'我的'}
  ]
  @Builder tabBuilder (item:TabClass,index:number){
    Column({space:5}){
      Text(item.text)
        .fontSize(16)
        .fontColor(this.currentIndex===index ? Color.Red : Color.Green)  // 根据索引切换颜色
    }
  }

  build() {
    NavDestination(){
      Tabs({barPosition:BarPosition.End}){
        ForEach(this.tabData,(item:TabClass,index:number)){
          TabContent () {
            if (this.currentIndex ===0){
              Home()
            } else if (this.currentIndex===1){
              Calculate()
            } else if (this.currentIndex===2){
              Settings()
            }

          }
          .tabBar(this.tabBuilder(item,index))  // 自定义导航
          .backgroundColor(Color.White)
          .expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])

        }
      }
      .onChange((index:number)=>{
        this.currentIndex = index  // 更新切换的索引
      })
      .backgroundColor(Color.Orange)
      .expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])

    }
    // .title("布局页")
    .onReady((context:NavDestinationContext) =>{
      this.pathStack = context.pathStack
    })
  }
}

Home.ets 页面:

interface GridClass {
  name: string
  cost: number
}

@Component
//export 导出,别的组件才可以导入去使用
export struct Home {
  // 创建一个页面栈对象并传入Navigation
  pathStack: NavPathStack = new NavPathStack();
  @State egDivider: DividerTmp = new DividerTmp(1, 0, 10, '#ffe9f0f0');
  

  build() {
    NavDestination() {
      Column() {

        Stack() {

          List({ space: 20 }) {
            ForEach(this.listData, (item: ListClass, index: number) => {
              ListItem() {

                Grid() {
                // 省略。。。。

                  GridItem() {
                    Column() {
                      Text(item.channel).margin({ top: 10 }).fontSize(12).width("100%")
                      Text("2025-02-03").margin({ top: 10 }).fontSize(12).width("100%")

                    }.width('100%').height("100%")
                  }
                }
                .columnsTemplate('1fr 1fr 1fr 1fr')
                .width('100%')
                .height(80)
              }
              .width('100%').backgroundColor('#FFF1F3F5')
              .onClick(() => {
                // 跳转到详细页面,并传入当前列表的数据
                console.log("开始跳转")
                let param:ParamClass = {
                  item:item,
                  list_index:index
                }
                this.pathStack.replacePathByName('Details',param)
              })

            })

          }
          .scrollBar(BarState.Auto)
          .alignListItem(ListItemAlign.Center)
          .width('100%')
          .divider(this.egDivider)
        }
        // .borderRadius(10)
        .clip(true)
        .width('100%')

      }
      .width('100%')
      .height('100%')
      .padding(10)
    }
    // 通过onReady获取导航上下文,初始化pathStack
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}

details.ets

import { ListClass } from "./Home";
import { List } from "@ohos.util.List";

@Builder
export function DetailsBuilder() {
  Details();
}





@Component
export struct Details {
  // 创建一个页面栈对象并传入Navigation
  pathStack: NavPathStack = new NavPathStack();
  
  // 接收从列表页传递过来的数据
  // @Prop item:ListClass;
  @Prop t:string

  build() {
    NavDestination() {
      Tabs({ barPosition: BarPosition.Start }) {
        TabContent () {
          // 调用信息组件,并传递数据
          // BuyInfo({
          //   item: this.item
          // }).width("100%")

          Text("hhhashdasd ")
        }
        .tabBar('测试一')


        TabContent () {
          Text('推荐的内容').fontSize(30)
        }
        .tabBar('测试二')

      }
    }
    .onReady((context:NavDestinationContext) => {
      this.pathStack = context.pathStack;
     
    })
  }
}

更多关于HarmonyOS 鸿蒙Next中Navigation路由导航失败闪退的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

Navigation路由导航失败闪退可能由以下原因导致:

  1. 页面路径配置错误:检查路由表router.json中的path配置是否正确,确保目标页面路径存在且拼写无误。

  2. 页面未注册:目标页面未在module.json5中声明,需确认所有导航目标页面都在"pages"数组中注册。

  3. 组件生命周期冲突:在aboutToAppear或aboutToDisappear中执行了同步阻塞操作导致ANR。

  4. 参数传递异常:传递的数据量过大或包含非法字符,建议检查params参数是否合规。

  5. 版本兼容性问题:某些API在鸿蒙Next版本中已废弃,需核对API变更说明。

更多关于HarmonyOS 鸿蒙Next中Navigation路由导航失败闪退的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


从代码和错误日志来看,问题出在Home.ets中的路由导航调用方式。主要问题有:

  1. 错误日志显示"is not callable",说明pathStack.replacePathByName调用方式不正确。在Home组件中,pathStack是通过@State或直接声明的方式创建的,但实际应该通过NavDestinationonReady回调获取。

  2. 在Home.ets中,你同时声明了两个pathStack

    • 一个是通过pathStack: NavPathStack = new NavPathStack()
    • 另一个是通过onReady回调获取的

解决方案:

修改Home.ets中的导航调用方式:

.onClick(() => {
  console.log("开始跳转")
  let param: ParamClass = {
    item: item,
    list_index: index
  }
  // 确保使用从onReady获取的pathStack实例
  this.pathStack.replacePathByName('Details', param)
})

同时确保:

  1. 在Home组件中只保留一个pathStack声明:
@State pathStack: NavPathStack = new NavPathStack();
  1. 确保Details页面在路由配置中已正确注册,且名称’Details’与注册时一致。

  2. 检查Details页面的参数接收方式,目前代码中使用了@Prop t: string但实际传递的是对象参数,这可能导致类型不匹配。

回到顶部