HarmonyOS 鸿蒙Next【小白学鸿蒙-学习笔记】关于鸿蒙的一点吐槽与近期学习的体会

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

HarmonyOS 鸿蒙Next【小白学鸿蒙-学习笔记】关于鸿蒙的一点吐槽与近期学习的体会
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

关于HarmonyOS 鸿蒙Next【小白学鸿蒙-学习笔记】关于鸿蒙的一点吐槽与近期学习的体会的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。

16 回复

<markdown _ngcontent-lku-c237="" class="markdownPreContainer">

前言

学习HarmonyOS也有一段时间了,发现了一些问题,也有一些体会,写在这里, 也是对自己近期的一个学习体会的总结。因为我之前是学Java的,没有安卓的相关开发经验,只有玩过一段时间的微信小程序,所以以下内容,如有错误,敬请指正。

吐槽

  1. 学习HarmonyOS最大的一个问题就是目前手头上没有合适的华为手机,借了一个Nova5Pro,结果当时不能升级到3.0系统,后面升级到了3.0系统之后,API版本还是6,导致一直都没有真机做测试,使用模拟器和预览器也勉强够用,不过学习过程中也有遇到一些Bug,后面再说

  2. 第二个问题就是HarmonyOS的版本跟API的版本,个人感觉有点混乱,因为你手上拿着一个设备,你是完全不知道它支持的API版本是多少,此处强烈建议华为的人想办法解决一下这个问题,有一个最简单的方式就是直接把API版本写在手机的开发者模式,这样进去就知道当前手机的API版本,这样不是比较简单吗?

  3. 感觉官方文档对于初学者来说并不是很友好,学习路线并不线性,官方文档表示,后期鸿蒙开发的主力肯定是ArkaTS+Storg模型,所以我选择直接先从API8入手,学习ArkTS,但是发现,对于ArkTS的学习,我个人之前只学过JS,对于TS的语法很多时候看到的时候一脸懵逼,但是官方文档对于这块内容好像默认你都会似的,也没写,只能自己去查,去摸索,增加了我的学习成本。

  4. CodeLabs的形式非常好,有用的内容也不少,但是一开始,我随便打开一个CodeLabs也是一脸懵逼的,为什么这么多文件,为什么这么多引用,对于初学者而言,不是应该简单点好理解一些比较好吗,但是CodeLabs目前的形式,个人感觉有点吓到我,并且对于CodeLabs的引导,给我一种,“我们来学习,这是1,这是2,这是3,1+1=2,1+2=3,你学会了吗?好了现在我们来造航母吧!”我个人感觉非常难受。不知道其他人会不会跟我有同样感觉。

吐槽就先吐槽到这里,接下来对目前学习的一个内容进行一个总结。

知识总结

对于这块内容,我是站在一个新手的角度得出的内容,如有不对的内容,请指正

入门:

基础:

了解:

熟悉:

重要

TS通用语法

类型

变量声明

name:type =  value
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

联合类型

  • 打个比方说image的src属性,传进去的参数可以是字符串也可以传一个资源路径,为什么可以这样呢?点进去看一下,他是这么写的:
src: string | PixelMap | Resource
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 在类型定义的时候,是用了"|",意思是可以是这个类型,也可以是另一个类型

数组类型

  • 最基础的很简单:
let numberArray: number[] = [1, 2, 3] // var numberArray = [1, 2, 3];
let numberArray1: Array<number> = [4, 5, 6] // var numberArray1 = [4, 5, 6];
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 联合类型也可以用数组:
let arr: (string | number)[] = [1, 'a']
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 复杂对象也可以用数组:
let arr: {name: string, age: number}[] = [
  {name: 'Jane', age: 17},
  {name: 'Jian', age: 20}
]
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

元组

  • 元组算是一个新东西,Python也有用到,本质上就是一个确定数量和类型的数组

  • 类型和位置需要一一对应

let data: [number, string, boolean] = [2, '3', true] // var data = [2, '3', true];
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

枚举

  • 这个也是使用enum枚举关键字,可以为枚举项赋值,不赋值默认从0开始,赋值后,这个值就是该枚举中枚举项的下标
enum Direction {
    Up = 1, // 不赋值默认从0开始
    Down,
    Left,
    Right
}

console.log(Direction.Down) // 2 console.log(Direction[1]) // Up <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

类型断言

  • 逻辑类似于Java的类型强转,有两种实现方式
str as string

<string>str //这两种方式都是将变量str,强制变成string类型 <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

类型别名

  • 使用type关键字可以给某一个Object对象起一个临时性的别名
type Lady = {name: string, age: number} // 对象类型可以使用类型别名
let arr: Lady[] = [
  {name: 'Jane', age: 17},
  {name: 'Jian', age: 20}
]
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

接口

接口提供一种数据结构的抽象定义,跟Java的会有所区别,不仅有方法的定义也有属性的定义,定义完了他就是一种数据结构

interface MyInterface {
name: string,
age: number,

say(): string }

function fn(opts: MyInterface) { //… }

fn({ name:“张三”, age:18, say(){ return “哈哈哈” } }) <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

接口的实现与继承

  • 跟Java一样,类使用implement关键字实现接口,实现接口后需要实现接口中的方法
  • 可以实现多个接口
  • 接口之间可以继承,A接口可以继承B接口和C接口,使用Extends关键字

属性声明

  • 跟Java有所区别,属性默认是Public的
  • Public在所有地方都可以访问
  • protectd受保护,在类内部和其子类中能够访问,实例中不能访问
  • private:私有,只能在内部访问。
  • readonly:只读,实例不能对这个属性赋值

构造函数关键字

  • 在类中,使用constructor关键字声明构造函数

静态成员

  • 跟Java一样,使用Static关键字修饰,修饰后无法使用this访问,必须使用类名调用和修改

存取器

  • 使用get\set修饰属性的同名函数,给私有属性一个存取方式,在存的时候可以设定一定的规则,不符合规则的不存

抽象类

  • 跟Java一样,抽象类不能用来创建对象,只是专门用来被继承的
  • 抽象类中可以有抽象方法和实例方法,抽象方法必须被子类实现,实例方法子类的实例对象可以直接调用

函数

函数类型

  • 在TS中,函数有两种类型,一种是函数声明,其实就是先定义函数,然后用到的时候,使用函数名调用

  • 另一种类似于Java的匿名函数,用到的时候直接使用function关键字创建一个函数

  • 函数的返回值跟属性的返回值一样,需要使用“:返回类型”

//函数声明
function sum(x: number, y: string): string {
  return x + y
}

//函数表达式 这种情况,sum的类型是ts自动推断得出的string类型 let sum = function (x: number, y: string): string { return x + y } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

  • 函数也可以成为属性的一种类型
let sum:(x:number,y:string)=>string
//属性sum为一个函数,函数形参为(x:number,y:string),返回值为string
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 函数表达式也可以简化成为箭头函数
(形参)=>{
    运算逻辑
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

可选参数

  • 当在组件或者函数中,某些参数可传可不传,就可以用到可选参数,使用方式如下,

  • 注意,如果一个函数中同时有必选参数和可选参数,可选参数一定要在后面

add(num?:number){

} <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

默认参数

  • 当使用上面的写法的时候,num是没有默认值的,如果我们在函数内有用到该参数,这样就可能会报错,这个时候可以使用默认值的方式,这样参数也是可以省略的,如果省略就会使用默认值
add(num:number=3){

} <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

剩余参数

  • 在Java中,这个叫可变参数,在指定函数的参数个数时,可能无法确定,那么可以将最后一个参数封装成为一个集合,然后在集合中遍历取出参数
function sum(x: number, ...rest: string[]): string[] {
  return rest.map(i => i + x)
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

函数重载

  • 在Java中也是有方法重载,同名的方法,根据传参的内容不同调用不同的方法,但是在Ts中,函数的每一个形参可以指定不同的参数类型,那么可以在函数内部进行参数判定,但是这种会比较麻烦,所以能用重载也可以用重载
function fn(x: number, y: number): number
function fn(x: string, y: string): string
function fn(x: string|number, y: string|number): string|number{
  if(typeof x === 'number' && typeof y === 'number') {
    return x + y
  } else if(typeof x === 'string' && typeof y === 'string') {
    return x + '_' + y
  } else {
    return '错误'
  }
}

// 如果没有前两个重载这里不会报错,输出内容是“错误” // 如果有了前两个重载这里就会报错,因为此时的参数不符合重载函数的任何一种传参数据类型 fn(10, ‘kkk’) <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

泛型

泛型函数

  • 泛型函数跟Java一样,可以让函数的参数类型在使用时决定。

泛型接口

  • 泛型接口跟泛型函数差不多

泛型类

  • 其实跟Java也差不多

TS中的This

  • 如果在箭头函数中,this指向的是当前组件,
  • 但是在如果使用匿名函数的方式,需要在事件后.bind(this)

ArkTS语法

UI描述

UI组件

  • 无参数构造组件

  • 有参数构造组件

组件名(参数){
    子组件
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

属性方法

  • 通过链式调用的方式
  • 参数可以传正常的参数外,可以使用枚举类型,具体的可以按进去,看需要传入什么参数

事件方法

  • 为当前组件绑定事件,当事件发生时可以进行响应
  • 使用方式有三种,一般建议使用前两种
  • 直接写箭头函数,
  • 把函数定义在外面,然后通过This.functionName调用(不用加括号)
  • 使用匿名函数,但是当函数体里面用到this关键字时,需要.bind(this),这个this指向当前组件

子组件配置

  • 当一个组件可以包含子组件时,子组件需要写在{ }里面
  • 子组件也可以嵌套其他的子组件

装饰器

带@ 就是装饰器,如[@State](/user/State)、[@Entry](/user/Entry)

组件定义装饰器

[@Component](/user/Component)
  • 简单理解,被修饰后,这就是一个组件了,可以复用
  • 如果想给其他页面复用,需要使用export关键字,然后对应页面使用 import关键字即可导入使用
[@Entry](/user/Entry)
  • 如果你想让一个组件单独以一个页面展示,那就需要用到这个修饰器,没什么好说的
  • 切记:是一个页面一个,我当时傻傻的以为入口嘛应该就一个,三个页面就index页面加了这个,结果毫无疑问的报错了
[@Rreview](/user/Rreview)
  • 学会用预览器之后就会发现,使用预览器还是挺爽的,但是预览器只能预览页面,也就是有加[@Entry](/user/Entry)的组件,如果我想预览自定义组件怎么办呢?这就需要用到[@Preview](/user/Preview)了,给自定义组件加上这个,就可以以组件的形式去预览了,所见即所得,还是挺爽的。

动态构建装饰器

[@Builder](/user/Builder)
  • 这个装饰器可以修饰一个函数,函数内部定义一个组件,可以达到复用的目的
  • 在定义动态组件的时候,可以声明一些参数,然后在组件内部使用它,这样当动态组件被使用的时候,可以传参进去,就达到动态复用的目的
[@Styles](/user/Styles)
  • 这个装饰器是用来降低重复的样式代码,不过它里面只能声明一些通用属性,不能声明组件特有的样式。
  • 并且两种使用方式:要么就在builder函数之前,要么就在当前组件之外,这样要加一个Function关键字
[@Extend](/user/Extend)
  • 如果你需要用到很多个Text组件,然后又不得不为他们定义相同的样式的时候,可以试试[@Extend](/user/Extend)关键字,它可以给基础组件快速扩展同一类样式。
  • 这个装饰器只能声明在当前组件的外面,并且也要Function关键字
[@CustonDialog](/user/CustonDialog)
  • 使用这个注解可以让你声明一个弹出框,并在想要的时候展示他
  • 步骤大概是,
  • 创建一个弹窗组件
  • 然后在父组件中创建对应的控制器,然后在控制器的构造函数中传入此弹窗组件及其他参数
  • 为当前页面的某一个组件绑定事件,当事件触发时,执行弹窗控制器的open方法
  • 具体的使用方式参照可以点击这里

状态管理装饰器

[@State](/user/State)
  • 这个装饰器用来修饰组件内部的变量,当该变量发生变化时,页面上应用该变量的内容会重新刷新
  • 这个只是单向绑定,修改值时并不会自动修改变量,所以需要绑定事件,在事件里修改变量,比如当这个值绑定一个输入框的时候,输入框中值的变化不会同步到该变量上,需要手动去修改
  • 在声明时要给定初始值
[@Prop](/user/Prop)
  • 这个装饰器修饰的变量声明在子组件中,但是初始化由父组件完成,父组件创建该子组件时,需要使用父组件的[@State](/user/State)变量去初始化它
  • 也可以理解为父组件的[@State](/user/State)变量绑定到了子组件的[@Prop](/user/Prop)变量上,当父组件的[@State](/user/State)变量发生变化时,使用到该[@Prop](/user/Prop)变量的组件也会发生变化,但是反过来就不会
  • 简单来说就是声明一个需要父组件传递过来的变量,谁用到我这个组件,谁就要给我传这个变量
[@Link](/user/Link)
  • 这个装饰器算是增强版的[@Prop](/user/Prop),因为它可以让父组件中的[@State](/user/State)变量跟子组件中[@Link](/user/Link)修饰的变量联动起来,当任一一方对变量进行修改时,会同步到另一方。

  • 值类型必须相同,不能在组件内部初始化,必须接收父组件的[@State](/user/State)变量初始化

  • 使用时需要使用$关键字,

子组件变量:$父组件变量
如text:$text
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
[@Watch](/user/Watch)
  • 这个装饰器用来监视某一个状态变量的变化,当发生变化时,就会调用该装饰器注册的函数

  • 使用方式为:

// [@State](/user/State) [@Watch](/user/Watch)("函数名")  变量名:变量类型= 初始值

@State @Watch(“add”) num:number = 0 //当num每一次发生变化时,就执行一次Add函数 add(){ this.xxx+=1 } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

[@Consume](/user/Consume)和[@Provide](/user/Provide)
  • [@Provide](/user/Provide)为数据的提供方,可以讲数据同步给其他被[@Consume](/user/Consume)修饰的变量,但是前提是,变量名需要一样

  • [@Consume](/user/Consume)为数据的接收方,本身不可以自行初始化变量,当感知到[@Provide](/user/Provide)数据的更新时,会触发当前组件的重新渲染。

  • 在使用[@Provide](/user/Provide)和[@Consume](/user/Consume)时,要避免循环引用导致死循环。

渲染控制

if/else

  • 这是很好理解的吧,为true就渲染该组件,为False就执行Else里面的组件

ForEach

  • 这个也很好理解,特别适合于那种样式一样只有内容不一样的组件内容填充
  • 使用需要三个东西,遍历的集合,渲染子组件的方法,生成Key值的方法

LazyForEach

  • 数据懒加载,使用这个它不会一下子把所有的加载出来,而是按需加载和创建

组件

容器组件

Flex

  • 弹性盒容器组件,默认是水平的主轴,跟垂直的交叉轴,也就是说是横向排列的
  • 可以设定FlexDirection,改变主轴的方向,变为列排列之类的等等
  • 也可以设定justifyContent,是主轴的对齐方式方式
  • 也可以设定AlignItems,设定交叉轴的对齐方式
  • 具体的可以看文档

Row

  • 行组件,容器内元素以行排列,也没啥好说的
  • 列默认的宽度是100%,横向占满一行
  • RowSplit:每个子组件加一道分割线

Column

  • 列组件,容器内元素以列排列,更没啥好说的
  • 列默认的高度是100%,纵向占满一列
  • ColumnSplit :每个子组件之间加一道分割线

List

  • 列表组件,常用于搭配ForEach实现统一类型元素的渲染
  • 内含ListItem

Tabs

  • 导航组件,内含TabContent作为页签,每一个页签对应着一个内容视图

Navigator

  • 路由容器组件,常用来套在某一个元素外面,为这个元素添加一个跳转效果,当该元素被点击时就执行跳转

Stack

  • 堆叠容器,就是栈的排列方式,先放进去的在最底下,然后一层一层铺上去

RelativeContainer

  • 相对布局组件,但是从API9才开始支持,API8不能用
  • 可以设置容器内组件相对于其他容器,或者相对于父容器的位置,相对来说比较自由,但是也比较繁琐的一个布局

Swiper

  • 滑动轮播组件,可以滑动,也可以轮播

GirdRow

  • 栅格容器组件,搭配GridCol使用,
  • 可以理解为把屏幕按比例分成若干个栅格,布局按栅格划分,在不同的屏幕尺寸上,栅格大小是不同的,所以占用屏幕尺寸也是会等比例缩小或者放大,从而实现屏幕大小的自适应

Grid

  • 网格容器,由行和列分割的单元格组成,由GridItem占用格的大小,来展现布局

Panel

  • 可以理解为一种可滑动的弹出框,可以用作应用内通知栏

Scroll

  • 可以滚动的容器组件,当子组件布局尺寸超过父组件时,可以滚动

SideBarContariner

  • 侧边栏组件,传入的第一个组件为侧边栏,就是展开的时候会显示出来的东西,第二个组件是主页面组件

Refresh

  • 下拉刷新动效,具体可以看文档

Badge

  • 标识组件,就是类似于微信的未读提醒

img

Counter

  • 计数器组件,在值的两侧有一个加减符号,可以分别设定回调函数,以实现加减功能
  • 可以加一个input组件,实现可以加减,也可以输入的功能
  • 目前有个Bug,当含有子组件时,设置子组件的margin属性,此时子组件就消失了

AlphabetIndexer

  • 字母索引条,一般用在通讯录应用啥的,

img

基础组件

Button

  • 按钮组件,具体看文档

Image

  • 图片组件,具体看文档

Text

  • 文本组件,具体看文档
  • 可以添加Span组件,用于给文本做一定装饰

TextInput

  • 文本输入框组件,具体看文档

Blank

  • 这个组件一定程度可以让我们的布局设计更简单,因为它是默认占据剩余的空白空间
  • 仅当父组件为Row/Column时生效,当父组件不设置宽度时,Blank失效,所以可以设置个最小宽度

Divder

  • 分割器组件

LoadingProgress

  • 加载动效的组件,具体看文档

Radio

  • 单选框组件,没啥说的,看文档

CheckBoxCheckboxGroup

  • 多选框组件,与全选,看文档
  • 有一点需要特别注意,当有用到CheckboxGroup时,该组件必须在最上面

Toogle

  • 勾选框样式、状态按钮样式、开关样式
  • 在使用时需要指定样式与默认状态

DataPanel

  • 数据面板组件,有线形跟环形两种样式,用于体现数据占比

滑动选择器

  • DatePicker:日期选择器
  • TextPicker:文本选择器
  • TimePicker:时间选择器
  • 这些选择器可以搭配Panel组件或者弹窗组件来进行弹出选择

Marquee

  • 跑马灯组件,当文本内容宽度超出组件宽度时,实现跑马灯样式的滚动效果

Navigation

  • 页面的根组件,可以用来设置页面的标题、工具栏、菜单等内容

TextClock

  • 将当前时间以文本形式展示

TextTimer

  • 文本计时器组件,可以正计时,倒计时、
  • 控制器可以开始、暂停、重置

下拉选择菜单

  • Select:给定一个数组,返回选择的数组下标

评分条

  • Rating:可用于电影评分之类的场景

滑动条

  • Slider:可用于滑动调节值

进度条

  • Progress:各种样式的进度条组件

二维码

  • QRCode:可以将Value转化成二维码图片进行展示

搜索框

分割器

  • Divider:提供一个分割条的样式,仅此而已

图表

  • Gauge:构建 一个环形图表,然后有一个指针指向当前数据所在的位置,可以理解为汽车上的速度指示器那种样式

媒体组件

Video

  • 视频播放组件,这个需要用到的时候,再去看吧

弹窗

警告弹窗:AlertDialog

  • 其他的弹窗也都差不多,可以看文档

资源的使用

  • 在开发过程中,肯定需要用到很多的资源,比如定义好的字符串、图片音频等,这些资源文件统一放在Resources目录下
  • 使用方式1:$r("app.type.name") 此方式可以调用base目录下的资源,切记,此方式下,不支持字符串拼接
  • 使用方式2:$rawfile("filename") 此方式直接使用rawfile目录下的文件(一般使用的是图片文件),并且需要包含文件后缀,此方式可以进行字符串拼接
  • 其他可以看文档

测验

完成以上内容的学习时,可以尝试完成测试

功能模块:

@ohos.router (页面路由)

  • router.push:跳转到指定页面
  • router.replace:使用页面替换当前页面,当前页面会被销毁
  • router.back:返回到上一页,或返回到指定页面
  • 可以传入一个参数:RouterOptions,该参数用于指定路由参数:跳转页面的url和传递的参数Params
  • router.getParams:在跳转后的页面中获取传入的参数,此参数为Object类型,需要使用router.getParams()['key']来获取对应的值

进阶

自定义组件的生命周期

aboutToAppear

  • 创建实例之后,build函数之前执行,可以在这里做一些数据的初始化操作

onPageShow

  • 仅对页面组件生效(也就是[@Entry](/user/Entry)修饰的组件)
  • 每次显示时触发一次,可以做开屏定时器之类的操作

onBackPress

  • 仅对页面组件生效(也就是[@Entry](/user/Entry)修饰的组件)
  • 用户点击手机上的返回按钮时触发,可以做一些提示性弹窗

onPageHide

  • 仅对页面组件生效(也就是[@Entry](/user/Entry)修饰的组件)
  • 页面每隐藏时触发一次,暂没有合适的应用场景

aboutToDisappear

  • 当前组件的实例被销毁之前执行,比如当前页被路由replace时
  • 不能在这个时候修改状态变量
  • 可以执行一些释放资源的操作

基础能力

Timer (定时器)

  • setTimeout:延时执行一个函数,仅执行一次,返回延时器的ID
  • clearTimeout:传入上面的ID,可以关闭此延时器
  • setInterval:周期性执行一个函数,一直重复执行,直到被清除,返回ID
  • clearInterval:传入上面的ID,可以清除该周期性任务

参考资料:

HarmonyOS图标库

CodeLabs

示例代码

3.1API

3.0API

HarmonyOS开发指南

HarmonyOS第一课

华为开发者论坛

HCIA-HarmonyOS 应用开发工程师课程V2.0

HCIA-HarmonyOS应用开发工程师认证V2.0

</markdown>

JS、TS默认你会很正常啊,这本来就是一门语言,不可能你去开发APP,人家官方文档还得教你基础语法的,这两个语言又不是鸿蒙开发的,而且基础语法网上大把教程,肯定先学语法再去开发呀。

API6-API7-API8-API9 航母模型,直升机航母,瓦良格航母,福特级航母

API6-API7-API8-API9-API10 明斯克舰(模型,旅游观光用),辽宁舰(瓦良格改的,实验用),山东舰(自己造的,可以开了,还是实验用),福建舰(全新设计-带电磁弹射等,初步定型),XX舰(上狠货…)

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

造航母这个确实。明明官方的学习文档只说了一些比较基础的知识,但是案例里面却是一个很复杂的内容,导致想跟着做也不知道在做什么。组件状态管里那章就是这样,我现在还是蒙的。。。

有一个问题,因为page.ets不能继承。
那么如果有多个page.ets且有一些通用的属性a,b,c。

通常我考虑继承,创建一个base.ets,把a,b,c属性放到base中。
但是api9应该怎么办呢。

不想每个page都定义一遍a,b,c属性。

导包导出去使用

有没有那种简单的demo示例。

我现在就是边学边复制,然后运行,改一改颜色和字体大小,看看效果

只能理解,不能记住

所有创新并非天生,过程:学习 > 复制 > 小改动 > 大改动/定制 > 思维突破/创新 :) 但是,记忆是基础,谁也绕不开:)

接触大概一周的时间了,我也遇到很多问题,大概总结一下

  1. 文档确实乱,而且给的示例dome里面都很基础,稍微复杂一点的功能估计都得摸索半天
  2. 基础组件确实太基础了,生态现在还很差,没有一些优秀的三方组件可以用,稍微复杂一点的东西都得自己写,比如一个抽屉组件,官方的SideBarContainer实在不够用,而且操作也很迷,不支持scroller,修改showSideBar的值还没有动画,类似的问题很多很多...
  3. 组件上下传值需要区分一下,ref的方式也没有,得用自定义Controller的方式
  4. 对于之前学前端的人来说,注解这个东西可能确实比较难理解,接触了这个概念以后就比较好一些了
  5. 编辑文件报错不够直接,特别是有时候报错会产出.js .js.map的文件,然后怎么编译都会报错,需要手动删一下
  6. 多层组件嵌套scroll不好使,具体原因还没找到。
  7. 不能直接使用[@Prop](/user/Prop) 或者 [@Link](/user/Link)的形式传递 Resource,子组件的图片组件无法显示,最好是搞个class再使用
  8. 没有图标的基础组件,也不支持iconfont 官方提供的图标只能下载下来,导入到项目里,自己再想办法用
  9. 编辑器的提示错误问题也有很多

我这边遇到的基本就上面的问题了,大部分轮子如果有社区提供,可以提升一下开发效率,可惜现在还没有,所以,还是再等等,或者自己造轮子吧,语法问题,肯定的熟悉,要不然啥也干不了。

我现在写代码没有太大问题了,头痛的还是生态问题。

新建一个系统和生态相当不易,这个大家应该能理解,要自己建造一个独立自主的体系既是不得已,也是必须的;但历史积累花时间才有积累;往好处想,现在是大家造自己的轮子的时候;不怕今后别人有轮子也不让你用的情况发生了。

回到顶部