鸿蒙面试心得

devtools/2024/9/18 13:31:45/ 标签: 面试, 职场和发展, 鸿蒙

自疫情过后,java和web前端都进入了冰河时代。年龄、薪资、学历都成了找工作路上躲不开的门槛。

年龄太大pass

薪资要高了pass

学历大专pass

好多好多pass

找工作的路上明明阳关普照,却有一种凄凄惨惨戚戚说不清道不明的“优雅”意境。

如何破局?

鸿蒙! 

好了废话不多说,下面进入正题

先聊一聊怎么学习鸿蒙

一、不建议报班

目前有好多培训班,对有web开发经验的人来说,我个人不建议报班。

要花费大量的时间

花费一定的money,现在钱不好赚能省则省吧

 那么我们如何开始学习鸿蒙呢?

二 、B站

现在B站里面黑马、千峰、尚硅谷已经出了多期基础视频,可以先看看这些视频,然后跟着老师把项目写一下,大概花两周的时间吧。

这样可以快速的了解什么是鸿蒙鸿蒙做了哪些事情,为以后的自己独立学习奠定基础

三、鸿蒙官方API 

HarmonyOS应用-HarmonyOS开发者-华为开发者联盟

文档中心

或者

鸿蒙 ArkTS 应用快速上手手册_w3cschool

如果兄弟们时间紧张可以先看下面这几个模块,一般看完面试就够用了

项目结构 

 

UI

如果ts薄弱可以看看这个

有框架的认知

有ts处理逻辑

有UI展示页面

这样一个APP大概就全了,如果兄弟们还有精力,那肯定是api研究的越全面越好啦

面试 

如果兄弟们这些都学完了,那么可以进行面试了:

需要注意的是面试分线下面试和线上面试

线下面试

如果是线下面试那兄弟们要注意了,可能要现场写代码,所以我建议先学完了我上面说的再去面试。如果写不出来白白浪费了一次机会。

不过线下写代码也不要担心,一般都是基础布局,在固定的时间内完成就行。

我先说一下我线下面试时需要注意的事项:

1. 如果大家习惯键盘和鼠标的话最好自己备上。

2. 面试官的需求文档一定要先看懂了,有全局的把控再开始写代码,不懂就问。

3. 得分点一定要清楚,而且都要实现

具体有哪些得分点,我给兄弟们举几个我在面试中遇到的

1.  用到组件化思想

2. 布局元素不能少,也就是和UI设计高度保真

3. 一些类型最好定义成枚举

4. 颜色变量定义到这里

5. http请求的封装

6. 列表尽量用LazyForEach提升性能

 线上面试

 我这里总结了一些:

1. Module类型

分为ability类型和Library类型

ability类型(重点知道什么是HAP)

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

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

Library类型的Module: (HAR、HSP)

用于实现代码和资源的共享。同一个Library类型的Module可以被其他的Module多次引用,合理地使用该类型的Module,能够降低开发和维护成本。Library类型的Module分为Static和Shared两种类型,编译后会生成共享包。

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

 说明

实际上,Shared Library编译后除了会生成一个.hsp文件,还会生成一个.har文件。这个.har文件中包含了HSP对外导出的接口,应用中的其他模块需要通过.har文件来引用HSP的功能。为了表述方便,我们通常认为Shared Library编译后生成HSP。

HAR与HSP两种共享包的主要区别体现在:

共享包类型编译和运行方式发布和引用方式
HARHAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝。HAR除了支持应用内引用,还可以独立打包发布,供其他应用引用。
HSPHSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。HSP一般随应用进行打包,当前只支持应用内引用,不支持独立发布和跨应用的引用。

 HAR和HSP在APP包中的形态示意图

2. Arkts相关(如果兄弟们精通ts可省略)

文档中心icon-default.png?t=N7T8https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/introduction-to-arkts-V5

  • 自定义组件:@Component装饰的UI单元,可以组合多个系统组件实现UI的复用,可以调用组件的生命周期。

  • 页面:即应用的UI页面。可以由一个或者多个自定义组件组成,@Entry装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个@Entry。只有被@Entry装饰的组件才可以调用页面的生命周期。

页面生命周期,即被@Entry装饰的组件生命周期,提供以下生命周期接口:

  • onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。

  • onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。

  • onBackPress:当用户点击返回按钮时触发。

组件生命周期,即一般用@Component装饰的自定义组件的生命周期,提供以下生命周期接口:

  • aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。

  • onDidBuild:组件build()函数执行完成之后回调该接口,不建议在onDidBuild函数中更改状态变量、使用animateTo等功能,这可能会导致不稳定的UI表现。

  • aboutToDisappear:aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。

生命周期流程如下图所示,下图展示的是被@Entry装饰的组件(页面)生命周期。

根据上面的流程图,我们从自定义组件的初始创建、重新渲染和删除来详细解释。

3.自定义组件的创建和渲染流程
  1. 自定义组件的创建:自定义组件的实例由ArkUI框架创建。

  2. 初始化自定义组件的成员变量:通过本地默认值或者构造方法传递参数来初始化自定义组件的成员变量,初始化顺序为成员变量的定义顺序。

  3. 如果开发者定义了aboutToAppear,则执行aboutToAppear方法。

  4. 在首次渲染的时候,执行build方法渲染系统组件,如果子组件为自定义组件,则创建自定义组件的实例。在首次渲染的过程中,框架会记录状态变量和组件的映射关系,当状态变量改变时,驱动其相关的组件刷新。

  5. 如果开发者定义了onDidBuild,则执行onDidBuild方法。

4. 自定义组件重新渲染

当事件句柄被触发(比如设置了点击事件,即触发点击事件)改变了状态变量时,或者LocalStorage / AppStorage中的属性更改,并导致绑定的状态变量更改其值时:

  1. 框架观察到了变化,将启动重新渲染。

  2. 根据框架持有的两个map(自定义组件的创建和渲染流程中第4步),框架可以知道该状态变量管理了哪些UI组件,以及这些UI组件对应的更新函数。执行这些UI组件的更新函数,实现最小化更新。

5. 自定义组件的删除

如果if组件的分支改变,或者ForEach循环渲染中数组的个数改变,组件将被删除:

  1. 在删除组件之前,将调用其aboutToDisappear生命周期函数,标记着该节点将要被销毁。ArkUI的节点删除机制是:后端节点直接从组件树上摘下,后端节点被销毁,对前端节点解引用,前端节点已经没有引用时,将被JS虚拟机垃圾回收。

  2. 自定义组件和它的变量将被删除,如果其有同步的变量,比如@Link、@Prop、@StorageLink,将从同步源上取消注册。

不建议在生命周期aboutToDisappear内使用async await,如果在生命周期的aboutToDisappear使用异步操作(Promise或者回调方法),自定义组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自定义组件的垃圾回收。

以下示例展示了生命周期的调用时机:

// Index.ets
import router from '@ohos.router';@Entry
@Component
struct MyComponent {@State showChild: boolean = true;@State btnColor:string = "#FF007DFF"// 只有被@Entry装饰的组件才可以调用页面的生命周期onPageShow() {console.info('Index onPageShow');}// 只有被@Entry装饰的组件才可以调用页面的生命周期onPageHide() {console.info('Index onPageHide');}// 只有被@Entry装饰的组件才可以调用页面的生命周期onBackPress() {console.info('Index onBackPress');this.btnColor ="#FFEE0606"return true // 返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理}// 组件生命周期aboutToAppear() {console.info('MyComponent aboutToAppear');}// 组件生命周期onDidBuild() {console.info('MyComponent onDidBuild');}// 组件生命周期aboutToDisappear() {console.info('MyComponent aboutToDisappear');}build() {Column() {// this.showChild为true,创建Child子组件,执行Child aboutToAppearif (this.showChild) {Child()}// this.showChild为false,删除Child子组件,执行Child aboutToDisappearButton('delete Child').margin(20).backgroundColor(this.btnColor).onClick(() => {this.showChild = false;})// push到page页面,执行onPageHideButton('push to next page').onClick(() => {router.pushUrl({ url: 'pages/page' });})}}
}@Component
struct Child {@State title: string = 'Hello World';// 组件生命周期aboutToDisappear() {console.info('[lifeCycle] Child aboutToDisappear')}// 组件生命周期onDidBuild() {console.info('[lifeCycle] Child onDidBuild');}// 组件生命周期aboutToAppear() {console.info('[lifeCycle] Child aboutToAppear')}build() {Text(this.title).fontSize(50).margin(20).onClick(() => {this.title = 'Hello ArkUI';})}
}
// page.ets
@Entry
@Component
struct page {@State textColor: Color = Color.Black;@State num: number = 0onPageShow() {this.num = 5}onPageHide() {console.log("page onPageHide");}onBackPress() { // 不设置返回值按照false处理this.textColor = Color.Greythis.num = 0}aboutToAppear() {this.textColor = Color.Blue}build() {Column() {Text(`num 的值为:${this.num}`).fontSize(30).fontWeight(FontWeight.Bold).fontColor(this.textColor).margin(20).onClick(() => {this.num += 5})}.width('100%')}
}

以上示例中,Index页面包含两个自定义组件,一个是被@Entry装饰的MyComponent,也是页面的入口组件,即页面的根节点;一个是Child,是MyComponent的子组件。只有@Entry装饰的节点才可以使页面级别的生命周期方法生效,因此在MyComponent中声明当前Index页面的页面生命周期函数(onPageShow / onPageHide / onBackPress)。MyComponent和其子组件Child分别声明了各自的组件级别生命周期函数(aboutToAppear / onDidBuild/aboutToDisappear)。

  • 应用冷启动的初始化流程为:MyComponent aboutToAppear --> MyComponent build --> MyComponent onDidBuild--> Child aboutToAppear --> Child build --> Child onDidBuild --> Index onPageShow。

  • 点击“delete Child”,if绑定的this.showChild变成false,删除Child组件,会执行Child aboutToDisappear方法。

  • 点击“push to next page”,调用router.pushUrl接口,跳转到另外一个页面,当前Index页面隐藏,执行页面生命周期Index onPageHide。此处调用的是router.pushUrl接口,Index页面被隐藏,并没有销毁,所以只调用onPageHide。跳转到新页面后,执行初始化新页面的生命周期的流程。

  • 如果调用的是router.replaceUrl,则当前Index页面被销毁,执行的生命周期流程将变为:Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。上文已经提到,组件的销毁是从组件树上直接摘下子树,所以先调用父组件的aboutToDisappear,再调用子组件的aboutToDisappear,然后执行初始化新页面的生命周期流程。

  • 点击返回按钮,触发页面生命周期Index onBackPress,且触发返回一个页面后会导致当前Index页面被销毁。

  • 最小化应用或者应用进入后台,触发Index onPageHide。当前Index页面没有被销毁,所以并不会执行组件的aboutToDisappear。应用回到前台,执行Index onPageShow。

  • 退出应用,执行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。

6. 自定义组件的冻结功能(要了解)

定义组件处于非激活状态时,状态变量将不响应更新,即@Watch不会调用,状态变量关联的节点不会刷新。通过freezeWhenInactive属性来决定是否使用冻结功能,不传参数时默认不使用。支持的场景有:页面路由,TabContent,LazyforEach,Navigation。

说明

从API version 11开始,支持自定义组件冻结功能。 

7. 常用装饰器

@Builder装饰器:自定义构建函数

@BuilderParam装饰器:引用@Builder函数

@Styles装饰器:定义组件重用样式

@Extend装饰器:定义扩展组件样式 

8. 状态管理

组件状态

  • @State:@State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关组件的渲染刷新。

  • @Prop:@Prop装饰的变量可以和父组件建立单向同步关系,@Prop装饰的变量是可变的,但修改不会同步回父组件。

  • @Link:@Link装饰的变量可以和父组件建立双向同步关系,子组件中@Link装饰变量的修改会同步给父组件中建立双向数据绑定的数据源,父组件的更新也会同步给@Link装饰的变量。

  • @Provide/@Consume:@Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。

  • @Observed:@Observed装饰class,需要观察多层嵌套场景的class需要被@Observed装饰。单独使用@Observed没有任何作用,需要和@ObjectLink、@Prop联用。

  • @ObjectLink:@ObjectLink装饰的变量接收@Observed装饰的class的实例,应用于观察多层嵌套场景,和父组件的数据源构建双向同步。

 应用状态

  • AppStorage是应用程序中的一个特殊的单例LocalStorage对象,是应用级的数据库,和进程绑定,通过@StorageProp和@StorageLink装饰器可以和组件联动。

  • AppStorage是应用状态的“中枢”,将需要与组件(UI)交互的数据存入AppStorage,比如持久化数据PersistentStorage和环境变量Environment。UI再通过AppStorage提供的装饰器或者API接口,访问这些数据。

  • 框架还提供了LocalStorage,AppStorage是LocalStorage特殊的单例。LocalStorage是应用程序声明的应用状态的内存“数据库”,通常用于页面级的状态共享,通过@LocalStorageProp和@LocalStorageLink装饰器可以和UI联动。

UI层面

布局种类:
  • 线性布局 (Row/Column)
  • 层叠布局 (Stack)
  • 弹性布局 (Flex)
  • 相对布局 (RelativeContainer)
  • 栅格布局 (GridRow/GridCol)
  • 媒体查询 (@ohos.mediaquery)
  • 创建列表 (List)
  • 创建网格 (Grid/GridItem)
  • 创建轮播 (Swiper)
  • 选项卡 (Tabs)
常用组件
  • 按钮 (Button)
  • 单选框 (Radio)
  • 切换按钮 (Toggle)
  • 进度条 (Progress)
  • 文本显示 (Text/Span)
  • 文本输入 (TextInput/TextArea)
  • 显示图片 (Image)
  • 自定义弹窗 (CustomDialog)
  • 视频播放 (Video)
  • 自定义绘制 (XComponent)
  • Native XComponent
 页面路由

文档中心icon-default.png?t=N7T8https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-routing-V5

鸿蒙中嵌套web(有时间可以了解,只在一次面试中问到)

文档中心icon-default.png?t=N7T8https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ui-js-overview-V5

 最后在简历层面我再浅说几点:

1. 要写上鸿蒙的经验,最少一年吧。为什么这么写,兄弟们要明白,你第一关要过的是HR,至于面试官信不信那不重要,面试官关注的是技术点。

2. 在个人优势里要尽量写鸿蒙相关的内容,基础也要写。还是那句话HR要看。

3. 面试的时候会就是会,不会就是不会。鸿蒙都是刚起步,不会不丢人,不要模棱两可。

4. 面试的时候语速要慢,尽量表达清晰。要自己先相信自己才能让面试官认可自己

5. 大家都是打工的,都是为了一个共同的方向在努力,没必要怯场,说话要平等大大方方的很重要

最后预祝大家面试成功!

如果兄弟们想一起学习鸿蒙,或者有面试相关的问题,简历问题,或者想一起分享总结的。可以评论区留言,加个联系方式,也可以私信弟弟。寒冬虽寒,但只要我们抱团取暖,总有那一线生机。


http://www.ppmy.cn/devtools/55885.html

相关文章

深入探讨计算机网络中的各种报文

在计算机网络中,报文(Packet)是数据传输的基本单位。不同的协议使用不同类型的报文来实现数据传输的各种功能。本文将详细探讨计算机网络中常见的几种报文类型,并通过举例说明其具体应用。 一、TCP/IP协议栈中的报文 TCP/IP协议…

Python机器学习分类算法(五)-- 最近邻算法(k-Nearest Neighbors,KNN)

最近邻算法原理 k-最近邻(k-Nearest Neighbors,KNN)算法是一种基本的机器学习分类和回归算法。在分类问题中,KNN通过测量不同特征值之间的距离来进行分类。它的工作原理是:存在一个样本数据集合,也称作训练…

[创业之路-131] :制造业企业的必备管理神器-ERP-初始实施中的难题与坑

目录 一、对ERP的误解 二、ERP常见的坑 三、ERP实施过程中,常见的管理问题 1、项目管理和沟通不畅 2、实施前基本的准备工作没做好 3、缺乏实施人才和实施计划 4、软件选择不当 5、制度支撑问题 四、ERP实施过程中,常见的技术问题 一、对ERP的误…

vue3-openlayers marker 光晕扩散(光环扩散)(postrender 事件和 render 方法)

本篇介绍一下使用 vue3-openlayers marker 光晕扩散(光环扩散)(postrender 事件和 render 方法) 1 需求 marker 光晕扩散(光环扩散) 2 分析 marker 光晕扩散(光环扩散)使用 post…

C++系统相关操作4 - 获取CPU(指令集)架构类型

1. 关键词2. sysutil.h3. sysutil.cpp4. 测试代码5. 运行结果6. 源码地址 1. 关键词 关键词: C 系统调用 CPU架构 指令集 跨平台 实现原理: Unix-like 系统: 可以通过 uname -m 命令获取 CPU 架构类型。Windows 系统: 可以通过环境变量 PROCESSOR_A…

数据结构与算法笔记:高级篇 - 概率统计:如何利用朴素贝叶斯算法过滤垃圾短信?

概述 上篇文章我们讲到,如何用位图、布隆过滤器,来过滤重复数据。本章,我们再讲一个跟过滤相关的问题,如果过滤垃圾短信? 垃圾短信和骚扰电话,我想每个人都收到过吧?买房、贷款、投资理财、开…

基于RK3568车载电脑助力日本巴士公司高效完成巴士到站系统项目部署

无处不在的物联网(IoT)技术已经渗透到了人类生活的各个角落,如日常出行乘坐的公交车上,物联网(IoT)技术的应用就得到完美诠释!其通过公交车上的车载电脑网络与中控室服务器连接来对公交车的运行…

6月27日-四象限法则

四象限法则,又称为艾森豪威尔矩阵(Eisenhower Matrix),是一种时间管理和任务优先级排序的方法。它将任务分为四个象限,帮助个人识别哪些任务最重要,哪些可以推迟或委托,以及哪些可以完全忽略。以…

qt经典界面框架

目的 其实就是一个简单的界面显示,是很常用的形式。 说起来简单也是简单,但当初,刚开始做时,感觉非常的复杂,不知如何下手。 现在感觉简单多了。 这个框架利用了QT的现成的MainWindow与QDockWidget,这样就…

太赞了!SD AI绘画,热门青衫映雪写真制作,一键出片,轻松复刻!【内含相关模型及ComfyUI工作流】

hello,大家好我是安琪! 今天安琪给大家带来了一篇关于写真制作,我通过SD WebUI进行本次青衫映雪主题的写真制作。(相关内容文末可自行扫描获取) 准备工作: 1.大模型准备真人写实大模型,我这里使用了TQing v3.4 2.…

react中如何获取并使用usestate声明的变量的值

1. 函数式更新 当需要根据当前状态来更新状态时,可以使用函数式更新。setState(在类组件中)和setCount(在useState中)都可以接受一个函数作为参数,这个函数接收当前的状态作为参数,并返回新的状…

MapReduce 实践题:Web 访问日志分析与异常检测

文章目录 作业描述MapReduce 实践题:Web 访问日志分析与异常检测题目背景数据集说明任务要求输入数据示例输出数据示例实现步骤 解题思路1. 数据预处理2. 访问统计3. 异常检测4. 主方法5. 结果输出 作业描述 MapReduce 实践题:Web 访问日志分析与异常检…

零知识学习之DPDK与RDMA(2)—— 认识DPDK(2)

接前一篇文章:零知识学习之DPDK与RDMA(1)—— 认识DPDK(1) 本文内容参考: 《Linux高性能网络详解 从DPDK、RDMA到XDP》 刘伟著 人民邮电出版社 https://blog.51cto.com/u_15301988/5181201 特此致谢&…

【知识学习】阐述Unity3D中Stencil的概念及使用方法示例

在Unity3D中,Stencil(模板)是一种高级的图形渲染技术,它允许开发者对渲染过程进行精细控制。Stencil Buffer是附加在颜色缓冲区和深度缓冲区之外的另一个缓冲区,它可以用来存储每个像素是否应该被渲染的信息。 Stenci…

【Python】 使用 pandas 中位数填充空值

那年夏天我和你躲在 这一大片宁静的海 直到后来我们都还在 对这个世界充满期待 今年冬天你已经不在 我的心空出了一块 很高兴遇见你 让我终究明白 回忆比真实精彩 🎵 王心凌《那年夏天宁静的海》 在数据分析和机器学习过程中,处理缺…

使用自定义的shiro密码匹配器CredentialsMatcher完成密码验证

今天突然想研究一下shiro怎么匹配用户的密码。 我们使用shiro的API登录时,会先创建一个令牌对象,而经常用的令牌对象是UsernamePasswordToken,把用户输入的用户名和密码作为参数构建一个UsernamePasswordToken,然后通过Subject.l…

AG32 MCU是否支持DFU下载实现USB升级

1、AG32 MCU是否支持DFU下载实现USB升级呢? 先说答案是NO. STM32 可以通过内置DFU实现USB升级,AG32 MCU目前不支持。但用户可以自己写一个DFU, 作为二次boot. 2、AG32 MCU可支持的下载方式有哪些呢? 我们AG32裸机下载只支持uart和…

Github 2024-06-21 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-06-21统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目3Python项目3Java项目2非开发语言项目2JavaScript项目1Rust项目1Dart项目1HTML项目1Vue项目1C++项目1TensorFlow: 机器学习的开源…

C#面:在C#项目中为什么使用接口?接口的好处是什么?什么是面向接口开发?

在C#项目中使用接口有以下几个好处: 实现多态性:接口允许一个类实现多个接口,从而使得一个类可以具有多种行为。这样可以提高代码的灵活性和可扩展性。实现代码的解耦:接口将类的实现与接口的定义分离,使得类与类之间…

Lua网站开发之文件表单上传

这个代码示例演示如何上传文件或图片,获取上传信息及保存文件到本地。 local fw require("fastweb") local request require("fastweb.request") local response require("fastweb.response") local cjson require("cjson&q…