鸿蒙学习坑点总结

421 阅读3分钟

解决方案参考列表

在进行项目开发时,为了快速完成项目迭代,可以优先参考现有的解决方案从而节约时间成本。

gitee.com/harmonyos-c…

developer.huawei.com/consumer/cn…

developer.huawei.com/consumer/cn…

developer.huawei.com/consumer/cn…

声明了构造函数的类实例化对象

代码如下:

class Person {
    name: string = ''
    age: number = 0
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

p: Person = {
    name: '小明',
    age: 18
}

interfaece IPerson {
    name: string
    age: number
}

q: IPerson = {
    name: '小米',
    age: 18
}

let a: {
    name: string
    age: number
}

解决办法如下:

1.不声明构造函数。

class Person {
  name: string = ''
  age: number = 0
}

p: Person = {
  name: '小明',
  age: 18
}

原理:类的兼容性。

2.使用new实例化对象

class Person {
    name: string = ''
    age: number = 0
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

p: Person = new Person('小明', 18)

真值的使用

在 JavaScript 和 TypeScript 中,真值是指那些在布尔上下文中被评估为 true 的值。所有非空字符串、非零数字、非空对象(包括数组)、true 本身等都被视为真值。

如果 || 运算符的两个操作数都是字符串,那么它将返回第一个被评估为真值的字符串。如果第一个字符串是真值(即非空字符串),则返回第一个字符串;如果第一个字符串是假值(即空字符串、nullundefined),则返回第二个字符串。

let str1: string = "";  // 空字符串,在布尔上下文中是假值
let str2: string = "Hello";  // 非空字符串,在布尔上下文中是真值

let result = str1 || str2;  // result 将是 "Hello",因为 str1 是假值

自定义组件 @Builder函数参数如何使用状态管理

调用@Builder装饰的函数默认按值传递。当传递的参数为状态变量时,状态变量的改变不会引起@Builder方法内的UI刷新。所以当使用状态变量的时候,推荐使用按引用传递

按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder方法内的UI刷新。

class Tmp {
  paramA1: string = ''
}

@Builder function overBuilder(params: Tmp) {
  Row() {
    Text(`UseStateVarByReference: ${params.paramA1} `)
  }
}
@Entry
@Component
struct Parent {
  @State label: string = 'Hello';
  build() {
    Column() {
      // Pass the this.label reference to the overBuilder component when the overBuilder component is called in the Parent component.
      overBuilder({ paramA1: this.label })
      Button('Click me').onClick(() => {
        // After Click me is clicked, the UI text changes from Hello to ArkUI.
        this.label = 'ArkUI';
      })
    }
  }
}

按引用传递参数时,如果在@Builder方法内调用自定义组件,ArkUI提供$$作为按引用传递参数的范式。

class Tmp {
  paramA1: string = ''
}

@Builder function overBuilder($$: Tmp) {
  Row() {
    Column() {
      Text(`overBuilder===${$$.paramA1}`)
      HelloComponent({message: $$.paramA1})
    }
  }
}

@Component
struct HelloComponent {
  @Prop message: string;

  build() {
    Row() {
      Text(`HelloComponent===${this.message}`)
    }
  }
}

@Entry
@Component
struct Parent {
  @State label: string = 'Hello';
  build() {
    Column() {
      // Pass the this.label reference to the overBuilder component when the overBuilder component is called in the Parent component.
      overBuilder({paramA1: this.label})
      Button('Click me').onClick(() => {
        // After Click me is clicked, the UI text changes from Hello to ArkUI.
        this.label = 'ArkUI';
      })
    }
  }
}

axios使用的注意点

需要区分请求的方法是post还是get。以及config中属性对应的get的query参数和post参数。

  // config
  {
        // 适用于get的query参数
      "params": {
        "ID": 12345
      },

      // 适用于post的参数
      "data": {
        "firstName": "Fred"
      },
  }

组件设置width('100%')与左右外边距的坑点

组件的尺寸 = 组件的内边距 + 边框 + 组件的内容尺寸。

组件使用外边距时需要考虑其尺寸+外边距是否超出父组件的尺寸。

例如在组件的宽度width('100%')时,设置左右外边距会发现边距不能正常的显示。

解决办法可以给组件外面再包一层容器Column或Row,然后设置左右padding。

Scroll组件滚动失效

Scroll组件有且只能有一个组件,当该组件的高度超过Scroll的高度时,Scroll滚动显示。不要将Scroll的组件的高度设置为'100%'。

预览器出现错误 / 效果无法显示

有没有一种可能,你现在做的东西预览器不支持,只能在真机或模拟器上正常显示。

注意GridCow的参数span和offer

span参数设置占据列的个数

offer参数设置当前列偏离原先位置的列数

模态转场的bindSheet一般绑定到页面的build下的子组件

若在ForEach中给多个组件绑定bindSheet则可能会出现显示崩溃问题

Scroll组件如何设置对齐方式

通过通用属性align()。

Tabs组件的标签个数少时(比如2个标签)无法左对齐

官方解决方案:developer.huawei.com/consumer/cn…

使用富文本解决HTML文本的显示

RichText(`
          <html>
          <body>
            <div style="font-size:54px">${this.item.answer}</div>

          <body>
          </html>

          `)

Web组件也可以解决HTML文本的显示问题,不过没有富文本方便。

通过route.getParam()获取参数使用后报错

需要先判空。

aboutToAppear(): void {
    const res = router.getParams() as RouterParams
    if (res) {
      this.currentTabBarIndex = res.index
    }
  }

TextInput的text参数绑定状态变量后输入文本未引起状态变量渲染

错误代码:

@State inputText: string = ''
TextInput({placeholder: '请输入关键词', text: this.inputText})

正解:

`$$`进行双向绑定。

@State inputText: string = ''
TextInput({placeholder: '请输入关键词', text: $$this.inputText})

组件设置背景色后没有显示

组件添加宽高属性或有内容才能观察到背景色。

Button组件设置圆角无效

需要设置Button的样式为Normal

Button({type: ButtonType.Normal}) { }

鸿蒙中只有Record类型和小写object的类型才可以通过[key值]方式取值

双层嵌套下滚动次序冲突如何解决?

内层滚动容器设置滚动优先级。

Scroll() {
  ....
  List() {
    ....
  }
  .nestedScroll({
    scrollForward: NestedScrollMode.PARENT_FIRST,
    scrollBackward: NestedScrollMode.SELF_FIRST
  })
}

拿屏幕的宽度

  • 第一种方式

每个系统组件都有onAreaChange事件,取第二个最新的参数

如果要拿屏幕的宽度,绑定最外层组件且最外层组件设置宽高100%

  • 第二种方式-display

display.getDefaultDisplaySync().width.toString()

SDK中系统资源的使用

HarmonyNext SDK中有一些比较常用的系统级icon图标、color字符串,具体的路径为你的sdk路径/default/openharmony/ets/build-tools/ets-loader/sysResource.js

使用方法

通过资源路径$r('system.media.xxxxxx')的方式使用系统SDK中自带的icon图标。具体的使用例子如下:

Image($r('sys.media.ohos_ic_public_arrow_up'))
    .width(20)
    .aspectRatio(1)

同样的,通过$r('system.color.xxxxxx')的方式可以使用系统SDK中自带的color字符串。

Row和Column主轴对齐的默认对齐

Row在主轴的默认对齐方式为靠左对齐。

Column在主轴的默认对齐方式为居中对齐。

组件设置了width('100%)和aspectRatio(1)后再设置margin出现的不可预料的现象

Column() {
  Image('xxxx')
    .width('100%')
    .aspectRatio(1)
    .margin({bottom: 10})
}
.width(200)
.height(200)

上面代码中Image无法占满父容器Colunm的宽度,会出现无法消除的间隙;

获取手机窗口中顶部状态栏和底部导航栏的高度

const win = await window.getLastWindow(ctx || getContext())
// 获取顶部状态栏的高度
const statHeight = px2vp(win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height)
// 获取底部导航栏的高度
const navHeight = px2vp(win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height)

如何设置应用全屏

// 开启全屏
async full(ctx?: Context) {
  const win = await window.getLastWindow(ctx || getContext())
  win.setWindowLayoutFullScreen(true)
}

// 退出全屏
async exitFull(ctx?: Context) {
  const win = await window.getLastWindow(ctx || getContext())
  win.setWindowLayoutFullScreen(false)
}

animation()属性永远写到一个组件的最后一个属性

animation()属性永远写到一个组件的最后一个属性, 否则可能导致动画不生效;

object对象传值简写

在 JavaScript 和 TypeScript 中,如果对象的属性名称和变量名相同,可以直接使用这种简写形式。

interface Person {
  name: string
  age?: number
}

let name: string = 'LingWu'
const p: Person = {name}