2024年鸿蒙最新鸿蒙4(2),高级HarmonyOS鸿蒙开发面试解答之线程篇

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

创建项目的配置介绍

Project name: 项目名
Bundle name: 包名,需要遵循com.jwz.项目名 这种规范,需要保证包名唯一
Save location: 项目保存路径
Compile SDK: SDK的版本(选择默认的就行)
Model: 选择默认的Stage就行
Enable Super Visual: (这里不用动)
Language: 开发语言需要勾选ArkTs(默认也是勾选)
Compatible SDK: 这个版本和上面一样,默认就行
Device type: 设备类型:Phone(手机) Tablet(平板),这两个可以都勾选

项目的各文件介绍

项目结构如下:
在这里插入图片描述
各个文件介绍:

  • 根目录下的几个文件均是配置文件,这个不用我们深入了解,重点关注的是文件夹带蓝色小方块的entry这个文件夹,这是项目入口模块(也叫: 入口Ability)
  • 展开entry,在路径下也是一堆配置文件,这个我们无须担心,重点关注src文件夹即可(需要了解这些配置信息可以查看官方文档,有详细介绍,点击链接直达)
  • 展开src文件夹有main(开发用的)和ohosTest(测试用的,我们无需关心),我们展开main即可
  • 展开main文件夹,同样有个json5后缀的配置文件(先不管),重点看另外两个ets和resources
  • resources资源文件夹,默认里面有个国际化配置(en_US和zh_CN),继续展开base里面的media可以看到里面的icon图标,这里是存放所有的静态资源的
  • ets文件夹展开里面有两个文件夹,其中pages就是鸿蒙软件的每个页面的代码存放了,展开发现有个index.ets,这个就是默认展示的页面了,将来会写更多的ets文件,就是更多的手机页面了

运行项目

点击软件右边的Previewer生成一个预览设备(首次展开会弹出欢迎界面,叉掉在进来就可以了)
在这里插入图片描述
这样,预览设备上面的页面就是我们index.ets文件代码编译出来的页面了

详解index.ets代码的含义

// @Entry @Component @State 装饰器: 用来装饰类结构、方法、变量
@Entry // 标记当前组件是入口组件,当页面跳转到新页面,则新页面也属于入口组件,当页面内引用别的自定义组件,则此自定义组件非入口组件
@Component //标记自定义组件
struct Index { // struct 自定义组件:可复用的UI单元
// @State 在开头讲过了,标记该变量是状态变量,值变化时会总发UI刷新
@State message: string = ‘Hello World’
build() { // build UI描述: 其内部以声明式方式描达UI结构
// Row Column Text等,都是内置组件: ArkUI提供的组件

//组件分类:
//容器组件:用来完成页面布局,例如 Row、Column
//基础组件:自带样式和功能的页面元素,例如 Text
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold) //字体加粗
.onClick(()=>{ // 事件方法:设置组件的事件回调
// 处理相关事件
console.log(‘111’) // 这个打印语句在下面控制台点击log那里可以看到
this.message = ‘hello 萧寂173’ //修改内容
})
}
.width(‘100%’)
}
.height(‘100%’)
// fontSize fontWeight width height 属性方法: 设置组件的UI样式
}
}

效果图
在这里插入图片描述

ArtUI

ArkUl的各种组件

Image组件

Image:图片显示组件
1 声明Image组件并设置图片源:
Image(src: string|PixlMap|Resource)

1-1.string格式,通常用来加载网络图片,需要申请网络访问权限: ohos.permission.INTERNET(注意,在模拟器可以正常访问网络图片,在真实设备上需要申请网络访问权限)
Image(‘https://xxx .png’)
1-2.PixelMap格式,可以加载像素图,常用在图片编辑中
Image(pixelMapobject) // 直接操作像素,使用比较繁琐,需要构建其对象再传给image
1-3.Resource格式,加载本地图片,推荐使用
Image( r ( ′ a p p . m e d i a , m a t e 6 0 ′ ) ) / / 访问的是 e n t r y . s r c . m a i n . r e s o u r c e s . b a s e . m e d i a 文件夹内的图片 , a p p . 为固定格式 , 可以省略文件后缀名 p n g I m a g e ( r( 'app.media,mate60' )) //访问的是entry.src.main.resources.base.media 文件夹内的图片,app.为固定格式,可以省略文件后缀名png Image( r(app.media,mate60))//访问的是entry.src.main.resources.base.media文件夹内的图片,app.为固定格式,可以省略文件后缀名pngImage(rawfile( ‘mate60.png’)) //访问的是entry.src.main.resources.rawfile文件夹内的图片,直接指定图片名,这里后缀名不能省略

2.添加图片属性(width,height,borderRadius为组件通用属性,interpolation只能在图片组件使用)
Image($r( ‘app.media,icon’ )).width(100) // 宽度
.height(120) // 高度
.borderRadius(10) // 边框圆角
.interpolation(ImageInterpolation.High) // 图片插值,当低分辨率图片放大会有很多锯齿,设置插值会把这些锯齿弥补起来,看起来清晰度会清晰,有高中低三个选择,这里选择了高

3.完整代码
@Entry
@Component
struct Index {
@State message: string = ‘Hello World’

build() {
Row() {
Column() {
Image(‘https://img-home.csdnimg.cn/images/20230825101811.png’).width(250) // 可以用百分比,也可以用数字(默认带vp参数,虚拟像素,会根据设备像素密度进行换算,可以保证同一个元素在不同设备上视觉大小是统一的,类似于rpx,rem)
Image($r(‘app.media.icon’)).width(250).interpolation(ImageInterpolation.High)
}
.width(‘100%’)
}
.height(‘100%’)
}
}

网络授权
申请网络访问权限文档:

在main/module.json5文件的module下面加入下面属性和值即可

“requestPermissions”: [
{
“name”: “ohos.permission.INTERNET”
}
],

Text组件

Text:文本显示组件
1.声明Text组件并设置文本内容
Text(content?: string|Resource)

1-1:string格式,直接填写文本内容
Text(‘图片宽度’)
1-2:Resource格式,读取本地资源文件
// 限定词目录存放的是国家,语言,设备等信息
// app.为固定前缀,string代表限定词目录(zh_CN和en_US)下的string.json(即国际化语言),width_label为string.json内name属性所对应的值
// 注意 同级的base目录下有个element文件夹,里面也有个string.json,这个文件是默认文件,当限定词在中英文里面都没有匹配的会来这里找(这里是默认的,不限于中英文),因此如果需要添加限定词,则这三个文件夹都需要改动
Text($r(‘app.string.width_label’))

2.添加文本属性
Text(‘注册账号’)
.lineHeight(32) // 行高
.fontsize(20) // 字体大小
.fontColor(‘#ff1876f8’) // 字体颜色.
.fontWeight(FontWeight.Medium) // 字体粗细

3.完整代码
@Entry
@Component
struct Index {
@State message: string = ‘Hello World’
build() {
Row() {
Column() {
Text($r(‘app.string.module_desc’))
.fontSize(25) // 设置字体大小
.fontWeight(FontWeight.Bold) // 字体加粗
}
.width(‘100%’)
}
.height(‘100%’)
}
}

TextInput组件

TextInput:文本输入框
1.声明TextInput组件:
TextInput( {placeholder?: ResourceStr, text?: ResourceStr})
1-1:placeHoder:输入框无输入时的提示文本
TextInput({placeholder:请输入账号或手机号"})
1-2:text:输入框当前的文本内容
TextInput({text:‘itcast’})

2.添加属性和事件
TextInput({text:‘当前输入文本’ })
.width(150) // 宽
.height(30) //高
.backgroundColor(‘#FFF’) // 背景色
.type(InputType.Password) // 输入框类型
.onChange(value=>{ // 输入框改变时触发,value为输入框的值
console.log(value)
})

3.完整代码
@Entry
@Component
struct Index {
@State message: string = ‘Hello World’

build() {
Row() {
Column() {
TextInput({text:‘当前输入文本’ })
.width(150) // 宽
.height(30) //高
.backgroundColor(‘#FFF’) // 背景色
.type(InputType.Password) // 输入框类型
.onChange(value=>{
console.log(value)
})
}
.width(‘100%’)
}
.height(‘100%’)
}
}

Button组件

Button:按钮组件
1.声明Button组件,label是按钮文字:
Button(label?: ResourceStr)

1-1:文字型按钮
Button(‘点我’)
1-2:自定义按钮,在Button内嵌套其它组件
Button(){
Image($r(‘app.media.search’ )) .width(20) .margin(10)
}

2.添加属性和事件
Button(‘点我’)
.width(100)
.height(30)
.type(ButtonType.Normal) // 按纽类型
.onClick(() => {
// 处理点击事件
}

Slider组件

slider:滑动条组件
Silder (options?: SliderOptions )

Slider({
min: 0,// 最小值
max: 10,// 最大值
value: 30,// 当前值
step: 0.1,// 滑动步长
style: SliderStyle.OutSet,// 决定滑块在里面还是外面
direction: Axis.Horizontal, // Vertical(垂直) 滑块方向(水平和垂直)
reverse: false // 是否反向滑动
})
.width(‘90%’) // 需要字符串百分比
.trackThickness(5) // 决定滑块粗细
.showTips(true) // 是否展示value百分比提示
.blockColor(‘#36d’) // 滑块背景色
.onChange(value=>{
// value就是当前滑块值
})

Column和Row组件

在这里插入图片描述

列就是Column容器,行就是Row容器
在这里插入图片描述

属性方法名说明参数
justifyContent设置子元素在主轴方向的对齐格式FlexAlign枚举
alignItems设置子元素在交叉轴方向的对齐格式Row容器使用VerticalAlign枚举,Column容器使用HorizontalAlign枚举

案例代码

@Entry
@Component
struct Index {
@State imagewidth: number = 30 // 定义图片宽度

build() {
Column({space:20}){ // space 间距
Text(‘item1’)
Text(‘item2’)
Text(‘item3’)
Text(‘item4’)
}
.width(‘100%’)
.height(‘100%’)
.justifyContent(FlexAlign.Center) // 对齐方式
.alignItems(HorizontalAlign.Center) // 交叉轴对齐方式
.layoutWeight(1) // 剩余空间分配(默认都是0,使用自己设置的宽高,设置为1之后,除了其他元素自身设置的宽高以外,其他的给设置为1的元素均匀分配,类似于html的flex:1)
}
}

分割线组件

Divider() // 放到两个组件之间,会出现一条线,作用等同于html的hr标签

撑满容器组件

Blank() // 在容器内部,其他组件都占满了一定空间,在两个组件之间加入blank可以直接将两个组件撑到最边上

List组件

列表(List)是一种复杂容器,具备下列特点:
1.列表项(ListItem)数量过多超出屏幕后,会自动提供滚动功能
2.列表项 (ListItem)既可以纵向排列,也可以横向排列

@Entry
@Component
struct Index {

build() {
List({space:80}){
ForEach([1,2,3,4,5,6,7,8,9,10,11,12,13],item=>{
ListItem(){
// 列表项内容,只能包含一个根组件
// 超出屏幕会显示滚动条
Text(“ListItem”)
}
})
}
.width(‘100%’)
.listDirection(Axis.Vertical) // 列表方向,Horizontal:水平,默认纵向(Vertical:垂直)
}
}

自定义组件

简单来说每个页面都是一个自定义组件,都有@component和@Entry修饰,但是@Entry标记当前自定义组件为入口组件,也就是页面组件,不能进行复用,则如果需要可复用的组件只需要把@Entry删除即可让组件可以进行复用

在同一个组件内部

// 子组件
@Component
struct Header{
@State message:string=‘’; // 接收父组件参数
build(){
Text(this.message) // 使用参数
}
}

// 父组件
@Entry
@Component
struct Index {
build() {
Row() {
Header({message:‘123’}) // 传值给子组件
}
.height(‘100%’)
}
}

定义在单独文件内,供全局使用
在ets下新建个components文件夹
在components下新建Header.ets文件,内容如下

// 子组件
@Component
export struct Header{
@State message:string=‘’;
build(){
Text(this.message)
}
}

在任意需要的父组件内使用

import {Header} from ‘…/components/Header’
// 父组件
@Entry
@Component
struct Index {
build() {
Row() {
Header({message:‘1234’})
}
.height(‘100%’)
}
}

自定义构建函数

全局

与自定义组件类似,但是这是一个函数,可以将组件中重复的代码封装到一个函数中,在需要的地方直接调用,不需要return返回

@Builder function xj(aaa:string){
Text(aaa) // 页面会显示’111222’
}

// 父组件
@Entry
@Component
struct Index {
build() {
Row() {
xj(‘111222’)
}
.height(‘100%’)
}
}

局部

// 父组件
@Entry
@Component
struct Index {
build() {
Row() {
// 局部定义需要添加this关键字才能调用
this.xj(‘111222’)
}
.height(‘100%’)
}

// 在局部定义不需要function关键字
@Builder xj(aaa:string){
Text(aaa) // 页面会显示’111222’
}
}

通用样式的设置

全局公共样式函数

// 定义全局公共样式函数
@Styles function xj(){
.height(‘100%’)
}

@Entry
@Component
struct Index {
build() {
Row() {
Text(‘你好’)
}
.xj() // 使用公共样式函数
}
}

局部公共样式函数

@Entry
@Component
struct Index {
// 定义局部样式函数
@Styles xj(){
.height(‘100%’)
}
build() {
Row() {
Text(‘你好’)
}
.xj() // 使用局部样式函数,这个不用加this
}
}

特殊样式(组件独有的样式,非公共样式)函数的封装

这种样式只能写在全局,没有局部

// 定义组件独有的样式函数
// 使用Extend继承,参数为继承的组件
@Extend(Text) function xj(){
.fontColor(‘#f36’)
.fontSize(18)
}

@Entry
@Component
struct Index {
build() {
Row() {
Text(‘你好’)
.xj() //使用
}
}
}

ArkUI的循环控制以及条件渲染

@Entry
@Component
struct Index {
@State items:any[]=[
{id:1,name:‘华为Mate60’,image:‘1.jpg’,price:6999,discount:1},
{id:2,name:‘华为X50’,image:‘2.jpg’,price:8799,discount:0},
{id:3,name:‘小米14’,image:‘3.jpg’,price:4379,discount:0},
{id:4,name:‘OPPOFind12’,image:‘4.jpg’,price:3299,discount:1},
{id:5,name:‘荣耀100’,image:‘5.jpg’,price:3799,discount:1}
]

build() {
Column(){
ForEach(
this.items,
(item,index)=>{
Row(){
if(item.discount){ // 条件控制,为0代表下架,也就是条件渲染
Text(index.toString()) // 数字要转成字符串,否则不显示
Image(item.image) // 因为类型是any,所以这里没提示,很正常
.width(100)
Column(){
Text(item.name)
Text(item.price.toString()) // 数字要转成字符串,否则不显示
}
.height(100)
}else{
Text(‘此商品已下架’)
}
}
},
(item,index)=>{
// foreact的第三个参数也可以不写,内部在循环时做好了key的处理
return item.id.toString() // 返回值为字符串,表示唯一性,类似于key
}
)
}
}
}

对象类型和类

使用@State监控对象类型

// 定义类,类里面为对象属性
class Person{
name:string
age:number

constructor(name:string,age:number) {
this.name=name
this.age =age
}
}

@Entry
@Component
struct Index {
@State p:Person = new Person(‘Jack’,21)
// 下面这种是数组的写法
// @State p:Array = [new Person(‘Jack’,21),new Person(‘Jack1’,22),new Person(‘Jack2’,23)]
build() {
Row() {
Text(姓名: ${this.p.name},年龄: ${this.p.age})
.onClick(()=>{
this.p.age+=1
})
}
}
}

对象内部嵌套对象写法

// 定义类,类里面为对象属性
class Person{
name:string
age:number
gf:Person
// 第三个可有可无,需要用?判断
constructor(name:string,age:number,gf?:Person) {
this.name=name
this.age =age
this.gf = gf
}

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

},年龄: ${this.p.age}`)
.onClick(()=>{
this.p.age+=1
})
}
}
}

对象内部嵌套对象写法

// 定义类,类里面为对象属性
class Person{
name:string
age:number
gf:Person
// 第三个可有可无,需要用?判断
constructor(name:string,age:number,gf?:Person) {
this.name=name
this.age =age
this.gf = gf
}

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


[外链图片转存中…(img-xajZvS5T-1715794901407)]
[外链图片转存中…(img-SN2kVmQI-1715794901407)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值