HarmonyOS鸿蒙Next中为什么函数加上export const localadd:local=new local

HarmonyOS鸿蒙Next中为什么函数加上export const localadd:local=new local layout代码为

import { find } from "./find";
import { local } from "./local";
import { mine } from "./mine";
import { recommend } from "./recommend";
import { HdsNavigation, HdsNavigationAttribute, HdsNavigationTitleMode, ScrollEffectType } from '[@kit](/user/kit).UIDesignKit';
import { AppStorageV2, LengthMetrics } from '[@kit](/user/kit).ArkUI';
import { PersistenceV2} from '[@kit](/user/kit).ArkUI';
import { GlobalMusic } from "../models/GlobalMusic"
import { playermanager } from "../untils/AVPlayerManager"
import { Background } from "../models/Background"
import {manager}from "./setting/custom"

// 跳转页面入口函数
interface zhuyemingzi {
  image: Resource,
  text: string
}

@Builder
export function layoutBuilder() {
  Layout();
}

export interface songsItem {
  img: string;   // 图像资源标识
  name: string;  // 资源名称
  author: string;// 作者信息
}
//AppStorageV2是临时的,PersistenceV2是永久的,两者语法一样
@ComponentV2
struct Layout {
  @Local Background: Background =  PersistenceV2.connect(Background, 'BACKGROUND_KEY', () => new Background())!
  @Local playState:GlobalMusic=AppStorageV2.connect(GlobalMusic,'SONG_KEY',()=>new GlobalMusic())!
  @Local pathStack : NavPathStack = AppStorageV2.connect(NavPathStack,'navstack',()=>new NavPathStack())!
  @Local currentindex: number = 0
  picture: zhuyemingzi[] = [
    { image: $r('app.media.home'), text: '推荐' },
    { image: $r('app.media.phone'), text: '本地' },
    { image: $r('app.media.communication'), text: '发现' },
    { image: $r('app.media.my'), text: '我的' }
  ]

  // 关键修改:CustomOverlay 清除底部偏移和结束对齐,改为顶部对齐
  @Builder CustomOverlay() {
    Column() {
      Column() {
        if (this.playState.playList&&this.playState.playList.length>0) {
          Row() {
            //图标
            Image(this.playState.albumCover)
              .shadow({
                color: Color.Gray,
                // 阴影颜色
                radius: 20,
                // 阴影模糊半径
                offsetY: 0,
                // 阴影Y轴偏移量(负值表示向上)
              })
              .width(40)
              .height(40)
              .margin({ left: 5 })
              .border({ radius: 10 })
              .onClick(() => {
                this.pathStack.pushPathByName('Play', null, true)
              })
            Column() {
              //歌名
              Text(this.playState.songName)
                .width('100%')
                .fontSize(17)
              //作者
              Text(this.playState.singerName)
                .width('100%')
                .fontSize(12)
                .margin({top:2})
            }
            .align(Alignment.Start)
            .padding({ left: 5 })
            .layoutWeight(1)
            //播放控制
            Image($r("app.media.ic_prev"))
              .fillColor(Color.Red)
              .width(30)
              .onClick(()=>{
                playermanager.prevPlay()
              })
            Image(this.playState.isPlay?$r('app.media.ic_paused'):$r('app.media.ic_play'))
              .margin({left:2})
              .fillColor(Color.Red)
              .width(35)
              .height(35)
              .onClick(()=>{
                this.playState.isPlay?playermanager.pasue():playermanager.singplay(this.playState.playList[this.playState.playIndex])
              })
            Image($r('app.media.ic_next'))
              .fillColor(Color.Red)
              .width(30)
              .margin({left:2})
          }
          .onClick(()=>{
            playermanager.nextPlay()
          })
          .width('100%')
          .justifyContent(FlexAlign.Start)
        }
        // 自定义组件放置区域(如按钮/图标)
        else {
          Row() {
            //图标
            Text('未在播放')
              .fontWeight(15)
              .fontSize(17)
              .textAlign(TextAlign.Center)
              .width('100%')
          }
          .width('100%')
          .justifyContent(FlexAlign.Start)
        }
      }
      .border({ radius: 10 })
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .shadow({
        color: Color.Gray,
        // 阴影颜色
        radius: 20,
        // 阴影模糊半径
        offsetY: 0,
        // 阴影Y轴偏移量(负值表示向上)
      })
      .backgroundBlurStyle(BlurStyle.COMPONENT_THICK)
      .width('95%')
    }
    .position({bottom:0})
    .margin({bottom:'11.5%'})
    .width('100%')
    .height(50) // 固定高度,避免占满屏幕
  }


  @Builder tabCustom(item: zhuyemingzi, index: number) {
    Column() {
      Image(item.image)
        .width(28)
        .height(28)
        .fillColor(this.currentindex === index ? '#85A880' : '#63AAAA')
        .margin({ top: 4 })
        .padding({ bottom: 4 })
      Text(item.text)
        .fontSize(15)
        .fontColor(this.currentindex === index ? '#85A880' : '#63AAAA')
    }
  }

  build() {

    NavDestination() {
      // ============ 核心修改:外层包裹 Stack 堆叠容器 ============
      Stack() {
        // ① 第一层:背景图片【优先级1】,无选择图片时显示默认背景色【优先级2】
        if (this.Background.currentbackground){
          Image(this.Background.currentbackground)
            .width('100%')
            .height('100%')
            .objectFit(ImageFit.Cover) // 铺满不变形,推荐使用
          // .objectFit(ImageFit.Contain) // 可选:完整显示图片,不裁剪,可能留边
        } else if(this.Background.currentbackground==='null'){
          // 无背景图时,使用默认背景色(和你原来的一致)
          Column()
            .width('100%')
            .height('100%')
            .backgroundColor($r('sys.color.ohos_id_color_background'))
        }

        // ② 第二层:你的原有页面内容(所有内容写在这里,会覆盖在背景图上)
        Column() {
          Tabs({ barPosition: BarPosition.End }) {
            ForEach(this.picture, (item: zhuyemingzi, index: number) => {
              TabContent() {
                if (index === 0) {
                  HdsNavigation() {
                    recommend()
                  }
                  .hideBackButton(true)
                  .titleMode(HdsNavigationTitleMode.MINI)
                  .titleBar({
                    avoidLayoutSafeArea: true,
                    style: {
                      scrollEffectOpts: {
                        enableScrollEffect: true,
                        scrollEffectType: ScrollEffectType.GRADIENT_BLUR,
                        blurEffectiveStartOffset: LengthMetrics.vp(0),
                        blurEffectiveEndOffset: LengthMetrics.vp(20)
                      },
                      originalStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      },
                      scrollEffectStyle: {
                        backgroundStyle: {
                          backgroundColor:$r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      }
                    },
                    content: {
                      title: {
                        mainTitle: '祝你天天开心'
                      },
                    }
                  })
                }
                else if (index === 1) {
                  HdsNavigation() {
                    local()
                  }
                  .hideBackButton(true)
                  .titleMode(HdsNavigationTitleMode.MINI)
                  .titleBar({
                    avoidLayoutSafeArea: true,
                    style: {
                      scrollEffectOpts: {
                        enableScrollEffect: true,
                        scrollEffectType: ScrollEffectType.GRADIENT_BLUR,
                        blurEffectiveStartOffset: LengthMetrics.vp(0),
                        blurEffectiveEndOffset: LengthMetrics.vp(20)
                      },
                      originalStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      },
                      scrollEffectStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      }
                    },
                    content: {
                      title: {
                        mainTitle: '本地'
                      },menu:{
                        value: [
                          {
                            content: {
                              label: '搜索',
                              icon: $r('app.media.ic_search'),   // ← 本地 svg/png
                              isEnabled: true,
                              action: () => console.info('点击了 搜索')
                            }
                          },{
                          content: {
                            label: '切换',
                            icon: $r('app.media.Switch'),   // ← 本地 svg/png
                            isEnabled: true,
                            action: () => console.info('点击了 切换')
                          }
                        },{
                          content: {
                            label: '导入',
                            icon: $r('app.media.add'),
                            isEnabled: true,
                            action: () => {

                            }
                          }
                        }]
                      }
                    }
                  })
                }
                else if (index === 2) {
                  HdsNavigation() {
                    find()
                  }
                  .hideBackButton(true)
                  .titleMode(HdsNavigationTitleMode.MINI)
                  .titleBar({
                    avoidLayoutSafeArea: true,
                    style: {
                      scrollEffectOpts: {
                        enableScrollEffect: true,
                        scrollEffectType: ScrollEffectType.GRADIENT_BLUR,
                        blurEffectiveStartOffset: LengthMetrics.vp(0),
                        blurEffectiveEndOffset: LengthMetrics.vp(20)
                      },
                      originalStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      },
                      scrollEffectStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      }
                    },
                    content: {
                      title: {
                        mainTitle: '互动大厅'
                      },menu:{
                        value: [
                          {
                            content: {
                              label: '添加',
                              icon: $r('app.media.add'),
                              isEnabled: true,
                              action: () =>{
                                manager.pickPhotoFromGallery()
                              }
                            }
                          }]
                      }
                    }
                  })
                }
                else if (index === 3) {
                  HdsNavigation() {
                    mine()
                  }
                  .hideBackButton(true)
                  .titleMode(HdsNavigationTitleMode.MINI)
                  .titleBar({
                    avoidLayoutSafeArea: true,
                    style: {
                      scrollEffectOpts: {
                        enableScrollEffect: true,
                        scrollEffectType: ScrollEffectType.GRADIENT_BLUR,
                        blurEffectiveStartOffset: LengthMetrics.vp(0),
                        blurEffectiveEndOffset: LengthMetrics.vp(20)
                      },
                      originalStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      },
                      scrollEffectStyle: {
                        backgroundStyle: {
                          backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
                        },
                        contentStyle: {
                          titleStyle: {
                            mainTitleColor: $r('sys.color.font_primary'),
                            subTitleColor: $r('sys.color.font_secondary')
                          },
                          menuStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          },
                          backIconStyle: {
                            backgroundColor: $r('sys.color.comp_background_tertiary'),
                            iconColor: $r('sys.color.icon_primary')
                          }
                        }
                      }
                    },
                    content: {
                      title: {
                        mainTitle: '我的'
                      }
                    }
                  })
                }
              }
              .tabBar(this.tabCustom(item, index))
            })
          }
          .overlay(this.CustomOverlay()) // Overlay 直接覆盖在 Tabs 上方,底部对齐 Tab 栏顶部
          .barHeight('14%') // Tab 栏高度固定为屏幕15%
          .scrollable(false)
          .barOverlap(true)
          .barBackgroundBlurStyle(BlurStyle.COMPONENT_THICK)
          .onChange((index: number) => {
            this.currentindex = index
          })
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.End)
      }
      .width('100%')
      .height('100%')
    }
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}

local代码为

import { AppStorageV2 } from "[@kit](/user/kit).ArkUI"
import { playermanager } from "../untils/AVPlayerManager";
import { GlobalMusic } from "../models/GlobalMusic";
import { getPersistPermissionUtils } from "../untils/PersistPermissionUtils";
import { addSongsBeforeLaunch, importSongs } from "../untils/ImportSongs";
import { manager} from "./setting/custom";
export interface SongInfo {
  uri: string;
  songName: string | Resource;
  duration: number;
  singerName?: string | Resource;
  albumCover?: PixelMap;
}

[@Component](/user/Component)
 export struct  local {
  [@StorageProp](/user/StorageProp)('topRectHeight') topRectHeight: number = 0;
  [@StorageProp](/user/StorageProp)('bottomRectHeight') bottomRectHeight: number = 0;
  [@State](/user/State) playList: Map<string, SongInfo> = new Map(); // 播放列表,使用 Map 去重
  [@State](/user/State) currentSong: SongInfo = {
    uri: '',
    duration: 0,
    songName: $r('app.string.unknown_song'),
    singerName: $r('app.string.unknown_singer')
  };

  async handleImportSongs() {
    importSongs(this.playList, this.context).then((songMap: Map<string, SongInfo>) => {
      this.playList = songMap;
    })
  }

  aboutToAppear(): void {
    getPersistPermissionUtils().init(this.context)
    this.initPlayListFromPf();
  }

  async initPlayListFromPf() {
    let existPath: Array<string> = await getPersistPermissionUtils().getFilePathExist(this.context)
    await getPersistPermissionUtils().activatePermissionExample(existPath)
    addSongsBeforeLaunch(existPath).then((songMap: Map<string, SongInfo>) => {
      this.playList = songMap

更多关于HarmonyOS鸿蒙Next中为什么函数加上export const localadd:local=new local的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

开发者您好,由于您提供的代码缺失的内容过多,我这边简化了一下您的写了一个demo:

@Component
export struct local{
  handleImportSongs(){
    console.log('play');
  }
  static handleImportSongs(){
    const instance = new local();
    instance.handleImportSongs()
    console.log('======================');
  }
  build() {
    Column(){
      Button('local').onClick(() => {
        this.handleImportSongs()
      })
    }
  }
}
import { local } from './local';
@Entry
@Component
struct layout{
  build() {
    Column({space: 10}){
      Button('layout')
        .onClick(() => {
          const instance = new local();
          local.handleImportSongs()
          instance.handleImportSongs()
        })
      local()
    }
  }
}

我在本地使用这个代码没有复现出来闪退的问题,开发者可以尝试一下这个代码是否有问题,如果有问题,还请开发者提供一下详细的日志信息以及版本信息(DevEco Studio版本信息和测试手机的版本信息)。

更多关于HarmonyOS鸿蒙Next中为什么函数加上export const localadd:local=new local的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


上面有@Component@ComponentV2混用了。 以及在local里面用了这个 pathStack: NavPathStack = AppStorageV2.connect(NavPathStack, ‘navstack’, () => new NavPathStack())! 所以会闪退。

闪退原因是这个吧:

cke_364.png

原因是:你在local里面写了这个:

pathStack: NavPathStack = AppStorageV2.connect(NavPathStack, 'navstack', () => new NavPathStack())!

解决办法:可以把上面那个报错行调整下位置,不要在页面初始化的时候就调用。

你好可以说一下具体怎么做吗,咋移位置🥹,

期待HarmonyOS能在未来带来更多创新的技术和理念。

local 是一个组件,组件基于struct声明而非class,因此不要使用new关键字进行实例化。

如果你需要复用local里面的逻辑,建议抽离出一个viewModel类, 专门用来处理逻辑。

下面简单示例,在viewModel中处理业务逻辑,管理状态变量:

export class LocalViewModel {
  context?: Context
  @Track message: string = '抽离viewModel'

  init(context?: Context) {
    this.context = context
  }
}

@Component
export struct local {
  @State viewModel: LocalViewModel = new LocalViewModel()

  aboutToAppear(): void {
    this.viewModel.init(this.getUIContext().getHostContext())
  }

  build() {
    Column() {
      Text(this.viewModel.message)
    }
  }
}

在HarmonyOS Next中,export const localadd:local=new local 是用于声明并导出一个常量 localadd,其类型为 local,并初始化为 new local() 实例。这通常用于定义本地服务或对象,以便在应用的不同模块中共享使用。export 关键字确保该常量可被其他文件导入,const 表示常量不可变。这种语法支持模块化开发,有助于代码组织和复用。

在HarmonyOS Next中,直接实例化一个自定义组件(如 new local())并导出为常量,然后在其他页面调用其方法,会导致页面闪退。这是因为自定义组件实例与UI渲染上下文紧密绑定,直接实例化会破坏组件的生命周期管理。

从你的代码看,local 组件已经有一个静态方法 handleImportSongs(context: Context),这是正确的设计。你应该直接调用这个静态方法,而不是创建组件实例。

解决方案:

在你的 layout.ets 文件中,修改 action 部分:

action: () => {
  // 获取当前页面的上下文
  const context = getContext(this) as Context;
  // 调用 local 组件的静态方法
  local.handleImportSongs(context);
}

原因分析:

  1. 组件生命周期问题@Component 装饰的组件需要由ArkUI框架管理其生命周期。直接使用 new local() 创建的实例没有正确的上下文绑定,会导致状态管理和资源释放异常。

  2. 上下文依赖handleImportSongs 方法需要 Context 对象来执行文件操作等系统功能。通过静态方法传递上下文是标准做法。

  3. 状态隔离:每个组件实例应有独立的状态。直接导出单例实例会导致状态污染和渲染冲突。

代码调整说明:

  • 移除 export const localadd: local = new local() 这行代码
  • 直接使用 local.handleImportSongs(context) 调用静态方法
  • 确保传入正确的 Context 对象

这样修改后,点击"导入"按钮就能正确调用 local 组件中的导入功能,而不会导致页面闪退。静态方法的设计正是为了支持这种跨组件的功能调用场景。

回到顶部