鸿蒙项目笔记(1)

news2025/4/3 17:12:32

一、核心内容-商城

1、装饰器的拓展使用,基础组件的熟悉。

2、引入基础动画实战,页面属性动画、页面跳转动画、自定义页面翻页等。

3、一次开发,多端部署。

4、本地数据库实战,涉及多种本地数据存储方式。

5、路由导航:路由的拦截,根据登陆的权限来定义页面显示。

6、扩展知识:地图、定位等。

7、媒体查询、响应式布局等。

二、项目应用模块

鸿蒙系统是:1+8+n的生态,即“1”是手机,“8”是各种周边生态像耳机、车机、平板等,“n”指智能家居、智能办公等等。考虑到当前的项目要适应多端,即“一多开发”,提出了新的开发模式,即多Module设计机制。

(1)多Module设计机制

1、支持模块化开发: 一个应用通常会包含多种功能,将不同的功能特性按模块来划分和管理,是一种良好的设计方式。通俗来讲就是可以将一个庞大的项目拆分为很多个模块,每个模块负责自己独立业务。有利于分工协作,便于我们项目功能划分和维护,每个模块可以独立编译、运行。他是鸿蒙系统提供的一种架构,按照指定模式来设计就能满足我们项目设计要求。

2、支持多设备适配: 一个应用往往需要适配多种设备类型,在采用多Module设计的应用中,每个Module都会标注所支持的设备类型。通俗来讲就是每个模块独立开发,并且每个模块都可以设置支持的设备类型,应用开发完成后上架市场,根据Module支持设备类型进行动态分配,如pad打开应用市场看到的就是支持pad的软件或者一些指定的模块。

(2)Module类型

Module按照使用场景可以分为两种类型:

1、Ability类型的Module:这种模块可以独立编译、打包运行,相当于一个公司的子公司,可以独立运行也可以和总公司一起运行。对应到项目中,商城项目为主模块,物流信息:可以设计为一个子模块,这个模块可以和主模块一起放在手机上运行,也可以独立的放在车机、手表上面运行。

每一个Ability类型的Module编译后,会生成一个以.hap为后缀的文件,我们称其为HAP(Harmony Ability Package)包。HAP包可以独立安装和运行,是应用安装的基本单位,一个应用中可以包含一个或多个HAP包,具体包含如下两种类型。

  • entry类型的Module:应用的主模块,包含应用的入口界面、入口图标和主功能特性,编译后生成entry类型的HAP。每一个应用分发到同一类型的设备上的应用程序包,只能包含唯一一个entry类型的HAP,也可以不包含。
  • feature类型的Module:应用的动态特性模块,编译后生成feature类型的HAP。一个应用中可以包含一个或多个feature类型的HAP,也可以不包含。

2、Library类型的Module: 用于实现代码和资源的共享。相当于公司里的各个部门,必须和总公司一起运行。对应到项目中,相当于一个庞大的项目我们可以拆分业务,放在每一个模块中运行,这些模块是无法独立打包运行,必须依赖整个项目。可以帮助我们分工协作,也可以帮助项目业务拆分后维护。一个模块类似于一个独立的项目,项目中要用到的公共工具或者代码,如果没有提取公共模块,每个模块重复写。

Library类型的Module分为Static和Shared两种类型,编译后会生成共享包。

  • Static Library:静态共享库。编译后会生成一个以.har为后缀的文件,即静态共享包HAR(Harmony Archive Package)。
  • Shared Library:动态共享库。编译后会生成一个以.hsp为后缀的文件,即动态共享包HSP(Harmony Shared Package)。

共享包类型编译和运行方式发布和引用方式
HAR

HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝。

注意:编译HAR时,建议开启混淆能力,保护代码资产。

HAR除了支持应用内引用,还可以独立打包发布,供其他应用引用。
HSPHSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。HSP一般随应用进行打包,当前支持应用内和集成态HSP。应用内HSP只支持应用内引用,集成态HSP支持发布到ohpm私仓和跨应用引用。

(3)HAP、HAR和HSP区别 

模块区别
HAP可以代表独立的项目,打包后缀名为hap,可以独立运行到设备,也可以独立上架应用市场。
HAR与HSP一样都是属于无法独立运行,但是可以将模块放在主模块使用,与HSP的区别在于:HAR模块一旦被主模块或者features模块使用,打包的时候独立打包一份代码放在对应模块中,所以多个模块使用,打包会打包多份文件,适合用于存放项目中指定某些业务,从主模块中独立出来,在商城项目中,可以将支付模块、购物车模块、商品列表都独立为HAR,在页面中引入使用。
HSP

type类型为shared,打包后的包名是hsp格式,无法独立编译和运行,必须依赖于entry或者application模块来运行。任何一个模块都可以引入shared模块中的内容,可以当成公共共享模块。

特点:多个模块引入shared模块内容,最终项目打包只会生成一个hsp模块进行代码的共享。

三、一次开发,多端部署 

随着终端设备形态日益多样化,分布式技术逐渐打破单一硬件边界,一个应用或服务,可以在不同的硬件设备之间随意调用、互助共享,让用户享受无缝的全场景体验。HarmonyOS系统面向多终端提供了“一次开发,多端部署”(后文中简称为“一多”)的能力,让开发者可以基于一种设计,高效构建多端可运行的应用。

一多开发主要包含两个层面:1、多个设备终端都 能适配运行,不同设备屏幕能看到不同的布局方案。2、根据不同终端设备打包为不同的HAP,在每一个终端设备中就能下载对应的安装包。

小设备

中设备

大设备

若要完成一多开发,我们需要将项目架构按照官方标准三层目录结构来设计

需要用到的技术:工程管理、媒体查询 、栅格系统,在开发过程中用媒体查询和栅格系统一起来实现页面的布局。

(1)工程管理

当遇到需要多端适配的项目时,推荐使用官方推荐的三层目录架构。以后所有HAP默认放在product;common就是HSP模块,用于存放公共工具和代码;features模块就是HAR模块,可以将项目拆分为无数个模块独立管理。

/application
 ├── common                  # 公共特性目录
 │
 ├── features                # 功能模块目录
 │   ├── feature1            # 子功能
 │   ├── feature2            # 子功能2
 │   └── ...                 # 子功能n
 │
 └── product                 # 产品层目录
     ├── wearable            # 智能穿戴泛类目录
     ├── default             # 默认设备泛类目录
     └── ...

按照官方文档,修改项目目录如下:

(2)媒体查询技术

1、基本概念与基础语法

响应式布局方式,可以检测当前设备大小,根据不同的屏幕尺寸用户自己决定如何布局。媒体查询技术是实现响应式布局的核心技术。

响应式布局能力

简介

断点

用户可以自己设置屏幕的参考值,以这个值为准让屏幕大小来匹配,匹配完成后就采用某种布局。

媒体查询

检测屏幕大小,检测设备类型。

栅格系统

在媒体查询技术上封装好的技术,鸿蒙提供的栅格系统

 媒体查询

 使用媒体查询来检测屏幕显示方式,下面代码中只用到了媒体查询的一个条件,只判断了横屏竖屏,要真正实现页面上元素的检测,尺寸的检测,可以添加更多的条件。

//(1)引入媒体查询对象
import mediaquery from '@ohos.mediaquery';
//目前官方提供从Kit中获取
import { mediaquery } from '@kit.ArkUI';
@Entry
@Component
struct Index {
  @State message:string = "媒体查询技术";
  //(2)检测屏幕是否为横屏,orientation:landscape查询条件:屏幕格式
  private listener =mediaquery.matchMediaSync('(orientation:landscape)')
  //(4)当满足媒体查询条件时,触发回调
  onPortrait = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    if (mediaQueryResult.matches) {
      AlertDialog.show({message:"横屏"})
    }else {
      AlertDialog.show({message:"竖屏"})
    }
  }
    //(3)给listener监听器绑定一个函数
  aboutToAppear(): void {
    this.listener.on("change",this.onPortrait)
  }
  build() {
    Column(){
      Text(this.message)
      .fontSize(50)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Green)
  }
}

2、媒体查询条件

内体查询条件是一个完整的表达方式,由媒体类型、逻辑操作符、媒体特征组成。

文档链接详情:媒体查询 (@ohos.mediaquery)-构建布局-开发布局-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

名称特征
媒体类型screen是默认的类型,不写也默认这个类型。一般将screen表示彩色屏幕。
逻辑操作符用于链接多个条件的符号,and:“与”;or:“或”;not:必须搭配screen使用,取反媒体查询结果;等等
媒体特征用于指定设备的范围,包含设备的状态、大小、名字。比较height、width等宽高尺寸,resolution分辨率,orientation屏幕的方向
private listener =mediaquery.matchMediaSync('(320vp<=width<600vp)')
//修改此处查询条件,根据不同的查询返回结果来定义不同的样式属性
//(1)引入媒体查询对象
import mediaquery from '@ohos.mediaquery';

@Entry
@Component
struct Index {
  @State message:string = "媒体查询技术";
  //(2)检测屏幕宽度
  private listener =mediaquery.matchMediaSync('(320vp<=width<600vp)')
  //(4)当满足媒体查询条件时,触发回调
  onPortrait = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    if (mediaQueryResult.matches) {
      AlertDialog.show({message:"手机"})
    }else {
      AlertDialog.show({message:"其他设备"})
    }
  }
    //(3)给listener监听器绑定一个函数
  aboutToAppear(): void {
    this.listener.on("change",this.onPortrait)
  }
  build() {
    Column(){
      Text(this.message)
      .fontSize(50)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Green)
  }
}

3、封装媒体查询工具 

需求:根据屏幕大小来自动识别我们的设备类型,设备尺寸目前主要分为xs,sm,md,lg,封装工具按照下面的断点来实现页面变化,检测设备的类型。

参考断点

断点名称

取值范围(vp)

xs

[0, 320)

sm

[320, 600)

md

[600, 840)

lg

[840, +∞)

3.1 媒体查询常量

在开发媒体查询的时候,我们会用到很多的数字或者一些值,这些数字或者值,尽量不要直接硬编码到代码中,有必要将代码中常用的参数封装到常量文件中,页面用来调用。在entry或者default的项目中未来让页面显示内容更加规范,因此也定义了一个常量文件,位置default/ets/constants/BasicConstants.ets

//default/src/main/ets/Constants/BasicConstants
//常量文件:封装了页面常用的一些值,封装好了以后可以直接引用,不用再写一遍
//减少页面数字、结果的硬编码
export class BasicContants{
  //常量要求变量名字必须大写 readonly只读
  static readonly FULL_WIDTH = '100%'
  static readonly FULL_HEIGHT = '100%'
  static readonly FONT_SIZE_SMALL = '14vp'
  static readonly FONT_SIZE_MEDIUM = '16vp'
  static readonly FONT_SIZE_BIG = '20vp'
  static readonly FONT_SIZE_LARGE = '30vp'
}

 在页面中使用:

import {BasicContants} from '../Constants/BasicContants'

@Entry
@Component
struct Index {
@State message:string = "常量使用";
  build() {
    Column(){
      Text(this.message)
      .fontSize(BasicContants.FONT_SIZE_LARGE)
    }
    .width(BasicContants.FULL_WIDTH)
    .height(BasicContants.FULL_HEIGHT)
  }
}
3.2 媒体查询工具: 

其属于公共开发工具,以后任何HAP模块,或者其他模块都可以使用这个工具,因此代码放在common的HSP模块中进行封装,哪个模块使用,直接引入共享。

3.2.1 封装常量

开发过程中,媒体查询有很多常量需要使用,这些常量都封装为一个媒体查询的常量文件,考虑到媒体查询工具是公用的工具,我们可以将这个工具放在common模块中的utils中,将常量文件放在common/src/main/ets/constants文件夹下,此处命名为BreakPointConstants,译为“媒体查询断电点常量”。

/**
*Constants for breakpoint
*/
export class BreakPointConstants{
  /**
  *这个单位页面上表示初始值
  */
  static readonly BREAKPOINT_INIT = 'init';
  /**
  * 这个单位页面上表示手机
  */
  static readonly BREAKPOINT_SM = 'sm';
  /**
  * 这个单位页面上表示折叠屏
  */
  static readonly BREAKPOINT_MD = 'md';
  /**
  * 这个单位页面上表示pad
  */
  static readonly BREAKPOINT_LG = 'lg';
  /**
  *这个单位页面上表示大屏
  */
  static readonly BREAKPOINT_XL = 'xl';
  /**
  *这个单位页面上表示超大屏
  */
  static readonly BREAKPOINT_XXL = 'xxl';
  /**
  *断点数组,根据不同的尺寸大小说明修改数组样式
  */
  static readonly BREAKPOINT_VALUE:Array<string> = ['320vp','600vp','840vp','1080vp','1280vp'];
  /**
  *列在水平方向占多少份
  */
  static readonly COLUMN_SM:string = '4';
  static readonly COLUMN_MD:string = '8';
  static readonly COLUMN_LG:string = '12';
  /**
  *
  */
  static readonly GUTTER_X:number = 12;
  /**
  *
  */
  static readonly SPAN_SM:number = 4;
  static readonly SPAN_MD:number = 6;
  static readonly SPAN_LG:number = 8;
  /**
  *
  */
  static readonly OFFSET_MD:number = 1;
  static readonly OFFSET_LG:number = 2;
  /**
  *
  */
  static readonly CURRENT_BREAKPOINT:string = 'currentbreakpoint';
  /**
  *
  */
  static readonly FONT_SIZE_SM:number = 14;
  static readonly FONT_SIZE_MD:number = 16;
  static readonly FONT_SIZE_LG:number = 18;
  /**
  *
  */
  static readonly COVER_MARGIN_SM:number = 10;
  static readonly COVER_MARGIN_MD:number = 30;
  static readonly COVER_MARGIN_LG:number = 40;
  /**
  *
  */
  static readonly RANGE_SM:string = '(320vp<=width<600vp)';
  static readonly RANGE_MD:string = '(600vp<=width<840vp)';
  static readonly RANGE_LG:string = '(840vp<=width<1080vp)';
  static readonly RANGE_XL:string = '(1080vp<=width<1280vp)';
  static readonly RANGE_XXL:string = '(1280vp<=width)';
}
3.2.2 封装媒体查询工具

在common/src/main/ets/utils创建一个媒体查询公共代码,BreakPointSystem.ets文件

import {BreakPointConstants} from '../constants/BreakPointConstants'
import { mediaquery } from '@kit.ArkUI'

export class BreakPointSystem{
  //当前尺寸是多大,媒体查询,得到单位要将这个sm、md、lg、xl、xxl保存到全局,currentBreakpint作为key保存起来
  private currentBreakpint:string = BreakPointConstants.BREAKPOINT_INIT
  /**
  *步骤一:屏幕大小的条件查询
  */
  private smListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_SM)
  private mdListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD)
  private lgListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG)
  private xlListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XL)
  private xxlListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XXL)


  //定义一个公共函数,用来保存当前屏幕的检测结果
  //将sm、md、lg、xl、xxl保存到“应用的状态”
  private updateCurrentBreakpoint(breakpoint:string){
    if (this.currentBreakpint !== breakpoint) {
      this.currentBreakpint = breakpoint
      //将当前单位做应用存储,setOrCreate是创建初始化的意思,()中存储一个键值,名字和存储内容
      AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT,this.currentBreakpint)
    }
  }
  /**
  *步骤二:给监听器绑定“change”事件
  */
  private isBreakpointSM = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    //如果匹配成功
    if (mediaQueryResult.matches) {
      //将sm的单位保存起来
      this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_SM)
    }
  }
  private isBreakpointMD = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    //如果匹配成功
    if (mediaQueryResult.matches) {
      //将md的单位保存起来
      this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_MD)
    }
  }
  private isBreakpointLG = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    //如果匹配成功
    if (mediaQueryResult.matches) {
      //将lg的单位保存起来
      this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_LG)
    }
  }
  private isBreakpointXL = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    //如果匹配成功
    if (mediaQueryResult.matches) {
      //将xl的单位保存起来
      this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_XL)
    }
  }
  private isBreakpointXXL = (mediaQueryResult: mediaquery.MediaQueryResult)=>{
    //如果匹配成功
    if (mediaQueryResult.matches) {
      //将xxl的单位保存起来
      this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_XXL)
    }
  }

  //这个函数外面要调用,因此不能再用private修饰
  public register(){
    this.smListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_SM);
    this.smListener.on('change',this.isBreakpointSM);
    this.mdListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD);
    this.mdListener.on('change',this.isBreakpointMD);
    this.lgListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG);
    this.lgListener.on('change',this.isBreakpointLG);
    this.xlListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XL);
    this.xlListener.on('change',this.isBreakpointXL);
    this.xxlListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XXL);
    this.xxlListener.on('change',this.isBreakpointXXL);
  }

  //接触事件绑定,优化代码
  public unregister(){
    this.smListener.off('change',this.isBreakpointSM);
    this.mdListener.off('change',this.isBreakpointMD);
    this.lgListener.off('change',this.isBreakpointLG);
    this.xlListener.off('change',this.isBreakpointXL);
    this.xxlListener.off('change',this.isBreakpointXXL);
  }
}
3.2.3 工具暴露 

在common/index.ets下

export { BreakPointConstants } from './src/main/ets/constants/BreakPointConstants'
export { BreakPointSystem } from './src/main/ets/utils/BreakPointSystem';
3.2.4 导入使用

在default/ets/Index.ets下,以后便可以根据得到的单位来决定页面如何布局,当检测sm的时候,一行显示两个商品,当检测md的时候,一行可以显示四个商品,当检测到lg的时候,一行可以多显示一些商品等响应式方案。

import {BreakPointSystem,BreakPointConstants} from '@ohos/common'
import {BasicContants} from '../Constants/BasicContants'

@Entry
@Component
struct Index {

  //暴露除一个类,需要new实例化才能使用
  private breakpointSystem = new BreakPointSystem()
  @StorageProp("currentbreakpoint") currentBreakpoint:string = BreakPointConstants.BREAKPOINT_INIT

  aboutToAppear(): void {
    //进入界面想要注册监听器,工具中已经将值传到了全局AppStorage
    this.breakpointSystem.register()
  }
  aboutToDisappear(): void {
    //组件销毁时要将监听器销毁,利于内存的回收
    this.breakpointSystem.unregister()
  }
  build() {
    Column(){
      Text(`当前屏幕尺寸单位类型为:${this.currentBreakpoint}`)
      .fontSize(BasicContants.FONT_SIZE_LARGE)
    }
    .width(BasicContants.FULL_WIDTH)
    .height(BasicContants.FULL_HEIGHT)
  }
}
3.3.5 注意事项

 1、因为工具封装暴露的是一个类,因此引入这个工具过后需要实例化一次。

 private breakpointSystem = new BreakPointSystem()

2、在页面生命周期中进行注册和销毁。

aboutToAppear(): void {
    //进入界面想要注册监听器,工具中已经将值传到了全局AppStorage
    this.breakpointSystem.register()
  }
  aboutToDisappear(): void {
    //组件销毁时要将监听器销毁,利于内存的回收
    this.breakpointSystem.unregister()
  }

3、通过应用存储获取当前检测到的屏幕尺寸。

@StorageProp("currentbreakpoint") currentBreakpoint:string = BreakPointConstants.BREAKPOINT_INIT

 4、如果想要在全局存储使用,但是不是页面或者组件中,而是在一个class类中进行只存操作,那么我们可以用setOrCreate来实现。

AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT,this.currentBreakpint)

 注意:新版本官方文档明确表示引用HSP的模块不支持预览,官方说明:

  • 预览不支持引用HSP。引用了HSP的模块不支持预览,请直接在HSP内预览或模拟HSP。

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-previewer-arkts-js-V5

书写时可以先在HAP或者HAR中实现,如有需要再往出抽离。

(3)栅格系统

栅格系统相当于鸿蒙已经封装好的组件,可以实现在页面布局中,根据屏幕大小来决定元素排列规则。栅格系统的底层其实也是用到了媒体查询技术。

栅格的样式由Margin、Gutter、Columns三个属性决定。

单个Column的宽度是系统结合Margin、Gutter和Columns自动计算的,不需要也不允许开发者手动配置。在实际使用场景中,可以根据需要配置不同断点下栅格组件中元素占据的列数,同时也可以调整Margin、Gutter、Columns的取值,从而实现不同的布局效果。

名称简介
Margin相对应用窗口、父容器的左右边缘的距离,决定了内容可展示的整体宽度。
Gutter相邻的两个Column之间的距离,决定内容间的紧密程度。
Columns栅格中的列数,其数值决定了内容的布局复杂度,默认最多12列。

1、栅格容器组件GridRow

栅格组件提供了丰富的断点定制能力,开发者可以修改断点的取值范围,支持启用最多6个断点。

//基础代码
@Entry
@Component
struct GridRowSample1 {
  @State bgcolors:Color[]=[Color.Red, Color.Blue, Color.Yellow, Color.Green, Color.Gray, Color.Black,Color.Pink,Color.Orange]
  build() {
    GridRow(){
      ForEach(this.bgcolors, (item:Color, index) => {
        GridCol(){
          Text(`${index}`)
            .textAlign(TextAlign.Center)
            .backgroundColor(item)
            .width(30)
            .height(100)
        }
      }, (item:Color, index) => JSON.stringify(item))
    }
  }
}

栅格组件(GridRow)的直接孩子节点只可以是栅格子组件(GridCol),默认一行最多显示12个元素,代表12列栅格布局,栅格布局是一种设计流程,很多框架都会采用,每一家框架的设计会有所区别。

1.1 GridRow支持参数

columns自定义设置一行最多显示多少列,用columns属性来控制。

//sm最多显示三列
GridRow({columns:3}){

}

可以指定根据不同的屏幕尺寸设计不同的元素排列个数。

//sm最多显示三列,md最多显示8列
GridRow({columns:{sm:4,md:8}}){

}

  breakpoints允许用户根据屏幕来自定义断点值。默认情况下,官方提供4个断点,最多支持6个断点。

断点名称取值范围(vp)
xs[0, 320)
sm[320, 600)
md[600, 840)
lg[840, +∞)
//sm最多显示三列,md最多显示8列
GridRow({columns:{sm:4,md:8}},
//自定义断点:200vp便是sm,300vp表示md......
         breakpoints:{value:['200vp','300vp','400vp','500vp','600vp']}
  ){
}

 direction可以设置容器里面子元素排列数序,主要是Row和RowReverse。

//sm最多显示三列,md最多显示8列
GridRow({columns:{sm:4,md:8}},
//自定义断点:200vp便是sm,300vp表示md......
         breakpoints:{value:['200vp','300vp','400vp','500vp','600vp']},
         direction:GridRowDirection.Row
  ){
}

 gutter设置子元素在水平方向排列过程中默认的间距。

//sm最多显示三列,md最多显示8列
GridRow({columns:{sm:4,md:8}},
//自定义断点:200vp便是sm,300vp表示md......
         breakpoints:{value:['200vp','300vp','400vp','500vp','600vp']},
         direction:GridRowDirection.Row,
         gutter:10
  ){
} 
1.2 子组件GridCol支持参数

GridCol组件支持配置span、offset和order三个参数。

//sm最多显示三列,md最多显示8列
GridRow({columns:{sm:4,md:8}}

  ){
      //span参数可以设置指定每一个单元格的份数
      GridCol({span:{sm:2,md:4},
      //offset可以通过这个属性来控制当前盒子的偏移份数,相当于设置了margin-left。
      offset:1,
      //order可以用来改变盒子排列的前后顺序
  }){
  }
} 
参数名类型必填默认值说明
span{xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?:number}-在栅格中占据的列数。span为0,意味着该元素既不参与布局计算,也不会被渲染。
offset{xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?:number}0相对于前一个栅格子组件偏移的列数。
order{xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?:number}0

元素的序号,根据栅格子组件的序号,从小到大对栅格子组件做排序。

2、栅格布局典型布局

典型页面场景-布局能力-页面开发的一多能力介绍-一次开发,多端部署 - 华为HarmonyOS开发者

四、Module构建流程

(1)HAP包构建流程

1、以一个单独的商城项目中地图功能作为一个模块为例,选中项目鼠标右键新建模块,

2、 回跳到选择构建模块类型,选择第一个,

 3、填写修改module名字,因为只能有一个entry,所以我们建立feature类型,可以有多个feature类型。

 4、默认Ability名字即可,

 5、创建成功,以后可以把地图、支付相关的一些功能独立出去放在这个模块,多个模块之间是可以进行通信的。

6、想要设置HAP打包后可以在什么设备运行,需要在/src/main/module.json下的“deviceTypes”中设置允许设备类型: 

 (2)HSP包构建流程

1、与上述构建HAP类型,但在选择模块时选择Shared Library

2、名字取名为common,

3、创建成功,在项目中我们一般只会创建一个shared模块,里面会放一些我们公共的工具包、公共组件都会存放在common模块中,其他ability模块中引入使用。

4、查看common模块类型,在common/module.json5下查看: 

 5、每个模块都能引入这个common模块中的内容,但是在最后打包的时候只会产生一份hsp代码,减少代码体积,以后修改了公共代码,其他页面都将直接修改。

6、暴露公共代码时,common里面写的代码基本上都是其他模块要用的公共代码,所以代码写完了将对象内容暴露出去,其他模块才能引入。在common/index.ets下书写,因此只要在这个文件暴露出去了指定组件、工具、插件等,其他模块就可以使用。

 7、common是一个独立的模块,里面的内容如果需要使用,需要将common模块引入到其他模块中做成一个依赖项,其他模块在开发代码的时候,找对应的某个函数,先找自己本身有没有,如果没有内容,就会去找依赖项中有没有,在oh_modules文件夹下存放自己的依赖和第三方依赖。比如common模块就是自己的依赖,axios属于第三方依赖。

 在devDependencies下将common包添加到全局依赖下

"devDependencies": {
    "@ohos/hypium": "1.0.21",
    "@ohos/hamock": "1.0.0",
    "@ohos/common": "file:./common"
  }

ps:写入后一定要记得执行Run,才算打包。

但这样会报错, 解决方法如下图:

 这样在@ohos下边有了相应的依赖包。

 (3)HAR包构建流程

1、在项目目录下创建一个文件夹features,

2、选中features,右键创建一个module,

3、根据模块需求定义模块名字,这个文件下创建的模块都是HAR模块,

4、打开指定模块的module.json5文件,

5、暴露公共代码时,在对应的模块中找到对应的index.ets ,

export { MainPage } from './src/main/ets/components/MainPage';

在主模块中引入指定homelibrary, 方法类似HSP需要在oh-package.json5修改,并且Run打包,

这样在相应位置便有了依赖包,可以在entry或者其他HAP处导入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

*快排延伸-自省排序

此节是学有余力的人去看&#xff0c;如果没时间&#xff0c;不看也没关系&#xff0c;只要知道代码就可以了&#xff01; 自省排序的思路是自我侦测和反省&#xff0c;快速排序如果递归深度太深&#xff0c;其算法的效率可能被大幅度削弱&#xff0c;这就需要借助其他的算法进…

三.微服务架构中的精妙设计:服务注册/服务发现-Eureka

一.使用注册中心背景 1.1服务远程调用问题 服务之间远程调⽤时, 我们的URL是写死的 String url "http://127.0.0.1:9090/product/" orderInfo.getProductId(); 缺点&#xff1a; 当更换机器, 或者新增机器时, 这个URL就需要跟着变更, 就需要去通知所有的相关服…

python-leetcode 63.搜索二维矩阵

题目&#xff1a; 给一个满足两条属性的m*n的整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列 每行的第一个整数大于前一行的最后一个整数 给一个整数target,如果target在矩阵中&#xff0c;返回true,否则返回false 方法一&#xff1a;两次二分查找 由于每…

音视频入门基础:MPEG2-TS专题(26)——通过FFmpeg命令使用RTP发送TS流

音视频入门基础&#xff1a;MPEG2-TS专题系列文章&#xff1a; 音视频入门基础&#xff1a;MPEG2-TS专题&#xff08;1&#xff09;——MPEG2-TS官方文档下载 音视频入门基础&#xff1a;MPEG2-TS专题&#xff08;2&#xff09;——使用FFmpeg命令生成ts文件 音视频入门基础…

blender二次元上色

前&#xff1a; 后&#xff1a;&#xff08;脸自己会发光) 参考&#xff1a;05-模型导入与材质整理_哔哩哔哩_bilibili

2025年2月一区SCI-壮丽细尾鹩莺算法Superb Fairy-wren Optimization-附Matlab免费代码

引言 本期介绍一种新的元启发式算法——壮丽细尾鹩莺优化算法Superb Fairy-wren Optimization algorithm&#xff0c;SFOA。该算法结合了壮丽细尾鹩莺群体中幼鸟的发育&#xff0c;繁殖后喂养幼鸟的行为&#xff0c;以及它们躲避捕食者的策略&#xff0c;于2025年2月最新发表在…

Hadoop•踩过的SHIT

听说这里是目录哦 ssh登录Permission denied, please try again&#x1f4a9;要发癫&#x1f972; centos7 yum报错&#xff1a;cannot find a valid baseurl for repo:base/7/x86_64&#x1f4a9;FinalShell重连失效&#x1f4a9;ssh免密登录显示 No route to host&#x1f4a…

闭环SOTA!北航DiffAD:基于扩散模型实现端到端自动驾驶「多任务闭环统一」

端到端自动驾驶目前是有望实现完全自动驾驶的一条有前景的途径。然而&#xff0c;现有的端到端自动驾驶系统通常采用主干网络与多任务头结合的方式&#xff0c;但是它们存在任务协调和系统复杂度高的问题。为此&#xff0c;本文提出了DiffAD&#xff0c;它统一了各种驾驶目标并…

Docker Registry 清理镜像最佳实践

文章目录 registry-clean1. 简介2. 功能3. 安装 docker4. 配置 docker5. 配置域名解析6. 部署 registry7. Registry API 管理8. 批量清理镜像9. 其他10. 参考registry-clean 1. 简介 registry-clean 是一个强大而高效的解决方案,旨在简化您的 Docker 镜像仓库管理。通过 reg…

JavaScript重难点突破:期约与异步函数

同步和异步 ​同步&#xff08;Synchronous&#xff09;​ ​定义&#xff1a;任务按顺序依次执行&#xff0c;前一个任务完成前&#xff0c;后续任务必须等待。 ​特点&#xff1a;阻塞性执行&#xff0c;程序逻辑直观&#xff0c;但效率较低 ​异步&#xff08;Asynchron…

蓝桥杯高频考点——高精度(含C++源码)

高精度 前言高精度加法例题思路及代码solution 1&#xff08;初阶版 40分&#xff09;solution 2&#xff08;完全体 AC&#xff09; 高精度乘法例题思路及代码solution 1&#xff08;TLE 但是代码很清晰&#xff09;solution 1的问题solution 2&#xff08;优化 AC&#xff09…

【机器人】复现 GraspNet 端到端抓取点估计 | PyTorch2.3 | CUDA12.1

GraspNet是通用物体抓取的大规模基准的基线模型&#xff0c;值得学习和复现。 本文分享使用较新版本的PyTorch和CUDA&#xff0c;来搭建开发环境。 论文地址&#xff1a;GraspNet-1Billion: A Large-Scale Benchmark for General Object Grasping 开源地址&#xff1a;https:…

视频联网平台智慧运维系统:智能时代的城市视觉中枢

引言&#xff1a;破解视频运维的"帕累托困境" 在智慧城市与数字化转型浪潮中&#xff0c;全球视频监控设备保有量已突破10亿台&#xff0c;日均产生的视频数据量超过10万PB。然而&#xff0c;传统运维模式正面临三重困境&#xff1a; 海量设备管理失序&#xff1a;…

《网络管理》实践环节03:snmp服务器上对网络设备和服务器进行初步监控

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 应用拓扑图 3.0准备工作 所有Linux服务器上&#xff08;服务器和Agent端&#xff09;安装下列工具 yum -y install net-snmp net-snmp-utils 保证所有的HCL网络设备和服务器相互间能…

ubuntu中使用安卓模拟器

本文这里介绍 使用 android studio Emulator &#xff0c; 当然也有 Anbox (Lightweight)&#xff0c; Waydroid (Best for Full Android Experience), 首先确保自己安装了 android studio &#xff1b; sudo apt update sudo apt install openjdk-11-jdk sudo snap install…

py数据结构day3

思维导图&#xff1a; 代码1&#xff08;完成双向循环链表的判空、尾插、遍历、尾删&#xff09;&#xff1a; class Node:def __init__(self, data):self.data dataself.next Noneself.prev Noneclass DoubleCycleLink:def __init__(self):self.head Noneself.tail None…

STM32单片机入门学习——第8节: [3-4] 按键控制LED光敏传感器控制蜂鸣器

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.02 STM32开发板学习——第8节: [3-4] 按键控制LED&光敏传感器控制蜂鸣器 前言开…

【JavaScript】十三、事件监听与事件类型

文章目录 1、事件监听1.1 案例&#xff1a;击关闭顶部广告1.2 案例&#xff1a;随机点名1.3 事件监听的版本 2、事件类型2.1 鼠标事件2.1.1 语法2.1.2 案例&#xff1a;轮播图主动切换 2.2 焦点事件2.2.1 语法2.2.2 案例&#xff1a;模拟小米搜索框 2.3 键盘事件2.3.1 语法2.3.…

通过ansible+docker-compose快速安装一主两从redis+三sentinel

目录 示例主机列表 架构参考 文件内容 安装脚本 ansible变量&#xff0c;需修改 ansible配置文件和主机清单&#xff0c;需修改 运行方式 验证故障转移master 涉及redis镜像和完整的脚本文件 示例主机列表 架构参考 文件内容 安装脚本 #!/bin/bashset -e export pa…

mysql docker容器启动遇到的问题整理

好几个月没折腾mysql的部署&#xff0c;弄了下&#xff0c;又遇到不少问题 问题一&#xff1a;Access denied for user ‘root‘‘172.18.0.1‘ docker容器启动后&#xff0c;本地navicat 连接报这个错误 查到两个方案&#xff0c;一个貌似是要让root用户能在任意ip地址&…