鸿蒙HarmonyOS4.0开发应用学习笔记

黑马程序员鸿蒙4.0视频学习笔记,供自己回顾使用。

1.安装开发工具DevEco Studio

鸿蒙harmony开发文档指南

DevEco Studio下载地址
鸿蒙开发工具官网
选择或者安装环境
在这里插入图片描述
选择和下载SDK
在这里插入图片描述
在这里插入图片描述
安装总览
请添加图片描述
编辑器界面
在这里插入图片描述

2.TypeScript语法

2.1变量声明

//string 、number、boolean、any、union、Object、Array
let s: string = 'hello world'
const ss: string = 'hello world'//const 代表常量
//any,个人不建议使用,代码量庞大后导致代码逻辑混乱
let a:any = '不确定类型,可能是任意类型'
//union
let u:string|number|boolean = '联合类型,可能是其中一种'
//Object,对象类型
let car = {brand:'问界',Price:199999}
console.log(car.brand)
console.log(car['brand'])
//Array:数组
let cars: Array<string> = ['问界','阿维塔']
let price: number[] = [199999,299999]
console.log(cars[0])
console.log(price[1])

2.2条件控制

//在TypeScript中,空字符串、数字0、null、undefined都被认为是false,其它值则为true
//if-else,写吐了不想写
if(){}else{}
if(){}else if(){}else{}
//switch
let season:string = '冬天'
switch(season){
	case '春天':{
		console.log('你的笑容那么美,恰好与春风撞了个满怀')
		break
	}
	case '夏天':{
		console.log('玫瑰到了花期,我很想你')
		break
	}
	case '秋天':{
		console.log('盛夏欠你的温柔,让秋风徐徐来还。')
		break
	}
	default{
		console.log('情话是学的,但爱你是真的')
		break
	}
}

2.3循环迭代

//for
for(let i = 0;i<100;i++){
	console.log('拥有'+i+'个男(女)模对象')
}
// for-in
let cars: string[] = ['问界','阿维塔']
for(const i in cars){
	console.log(cars[i])
}
//for-of
for(const car of cars){
	console.log(car)
}
//while
let i = 1;
while(i <= 100){
	console.log('拥有'+i+'个男(女)模对象')
	i++;
}

2.4函数

//无返回值
function func1(car:string):void{
	console.log(car)
}
fun1('问界')
//有返回值
function func2(x: number,y:number):number{
	return x+y 
}
let count = func2(1,1)
console.log('1+1=3?'+'1+1='+count)
//简写版,箭头函数
let func3 = (car:string) => {
	console.log(car)
}
func3('阿维塔')
//函数可选参数
function func4(car?:string){
	car = car?car:'哦莫'
	console.log(car)
}
func4()
func4('link')
//函数可选参数,提供默认值
function func5(car:string='哦莫'){
	console.log(car)
}
func5()
func5('link')

2.5类和接口

//定义枚举
enum GamesConsole{
	SWITCH:1999,
	PS5:2999,
	XBOXONE:2999
}
//定义接口,抽象方法接受枚举参数
interface Price{
	//类和对象里的函数不需要加function
	showPS5Price(price:GamesConsole):void
}
//实现接口
class Article implements Price{
	showPS5Price(price:GamesConsole):void{
		console.log('ps5的价格是:'+price)
	}
}
//初始化对象
let p:Price = new Article()
//调用方法,传递枚举参数
p.showPrice(GamesConsole.PS5)
//父类
class Rectangle{
	//成员变量
	private width:number
	private length:number
	//构造函数
	constructor(width:number,length:number){
		this.width=width
		this.length=length
	}
	//成员方法
	public area():number{
		return this.width * this.length
	}
}
//子类
class Square extends Rectangle{
	constructor(side:number){
		//调用父类构造
		super(side,side)
	}
}

let s = new Square(10)
console.log(s.area())

2.6模块开发

通用功能抽取到单独的ts文件,每个文件都是一个模块(module)。
模块可以相互加载,提高代码复用性。

//rectangle.ts
//定义类,通过export导出
export class Rectangle{
	//成员变量
	private width:number
	private length:number
	//构造函数
	constructor(width:number,length:number){
		this.width=width
		this.length=length
	}
}
//定义工具方法,通过export导出
export function area(rec:Rectangle):number{
	return rec.width * rec.length
}
//index.ts
//通过import导入,from后面写文件的地址
import {Rectangle,area} from '../rectangle'

//创建Rectangle对象
let r = new Rectangle(10,10)

//调用area方法
console.log('面积为:'+area(r))

3.快速入门-hello world

create project -> empty ability
在这里插入图片描述
Index.ets文件解读

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            //...处理事件
            if (this.message == 'Hello World') {
 				this.message = '你好 世界'
            }else {
            	this.message = 'Hello World'
            }

          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

在这里插入图片描述

4.ArkUI组件

4.1Image组件

Image:图片显示组件

1.声明Image组件并设置图片源:

Image(src: string|PixelMap|Resource)

① string格式,通常用来加载网络图片,需要申请网络访问权限: ohos.permission.INTERNET

Image('https://xxx . png' )

② PixelMap格式,可以加载像素图,常用在图片编辑中

Image(PixelMapObeject)

③ Resource格式,加载本地图片,推荐使用

Image($r('app.media.mate60'))
Image($rawfile('mate60.png'))

2.添加图片属性

Image($r('app .media.icon'))
	.width(100) //宽度
	.height(120) //高度
	.borderRadius(10) // 边框圆角
	.interpolation(ImageInterpolation.High) // 图片插值

4.2Text组件

Text:文本显示组件
1.声明Text组件并设置文本内容

Text(content?:string|Resource)

①string格式,直接填写文本内容

Text('今天天气很好呀!')

②Resource格式,读取本地资源文件

Text($r('app.string.hello'))

2。添加文本属性

Text('注册账号')
	.lineHeight(32) // 行高
	.fontSize(20) // 字体大小
	.fontColor('#ff1876f8') // 字体颜色
	.fontWeight(FontWeight.Medium) // 字体粗细

4.3TextInput组件

TextInput:文本输入框
1.声明TextInput组件

TextInput( {placeholder?: ResourceStr,text?: ResourceStr})

①placeHoder:输入框无输入时的提示文本

TextInput([placeholder:'请输入账号或手机号'})

②text: 输入框当前的文本内容

TextInput({text: '1234567890'})

2.添加属性和事件

TextInput({text:当前输入文本)
	.width(150) //宽
	.height(30) // 高
	.backgroundColor('#FFF') // 背景色
	.type(InputType.Password)//输入框类型
	.onChange(value=>{
		//value是用户输入的文本内容
	})
名称描述
Normal基本输入模式。支持输入数字、字母、下划线、空格、特殊字符。
Password密码输入模式。支持输入数字、字母、下划线、空格、特殊字符。
Email邮箱地址输入模式。支持数字,字母,下划线,以及@字符。
Number纯数字输入模式。
PhoneNumber9+电话号码输入模式。支持输入数字、+、-、*、#,长度不限。

4.4 Button组件

Button:按钮组件
1.声明Button组件,label是按钮文字:

Button(label?:ResourceStr)

① 文字型按钮

Button('点我')

② 自定义按钮,在Button内嵌套其它组件

Button(){
	Image($r('app.media.search')).width(20).margin(10)
}

2.添加属性和事件

Button('点我')
	.width(100)
	.height(30)
	.type(ButtonType.Normal)//按钮类型
	.onclick(()=>{
		//处理点击事件
	})

4.5 Slider组件

Slider:滑动条组件

Slider(options?:SliderOptions)
Slider({
	min:0,//最小值
	max:100,//最大值
	value:30,//当前值
	step:10,//滑动步长
	style:SliderStyle.OutSet,//Inset
	direction:Axis.Horizontal,//Vertical
	reverse:false//是否反向滑动
})
	.width('90%')
	.showTips(true)//是否展示value百分比提示
	.blockColor('#36D')
	.onChangge(value=>{
		//value就是当前滑块值
	})

4.6 Column和Row

属性方法名说明参数
justifyContent设置子元素在主轴方向的对其格式FlexAlign枚举
alignItems设置子元素在交叉轴方向的对其格式Row容器使用VerticalAlign枚举
alignItems设置子元素在交叉轴方向的对其格式Column容器使用HorizontalAlign枚举
FlexAlign枚举:
	FlexAlign.Start
	FlexAlign.Center
	FlexAlign.End
	FlexAlign.SpaceBetween
	FlexAlign.SpaceAround
	FlexAlign.SpaceEvenly

在这里插入图片描述

HorizontalAlign枚举:
	HorizontalAlign.Start
	HorizontalAlign.Center
	HorizontalAlign.End

在这里插入图片描述

VerticalAlign枚举:
	VerticalAlign.start
	VerticalAlign.Center
	VerticalAlign.End

在这里插入图片描述

4.7 循环控制

  • ForEach
  • if-else
    在这里插入图片描述

4.8 List

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

List({space:10}){
  ForEach([1,2,3,4],item => {
    ListItem(){
      //列表项内容,只能包含一个根组件
      Text('ListItem')
    }
  })
}
.width('100%')

4.9 自定义组件

  • 创建自定义组件
  • @Buider
  • @Styles

@Buider
在这里插入图片描述
@style
在这里插入图片描述
@Extend不仅可以写特有属性方法还可以写事件方法

5.ArkUI-状态管理

5.1@State装饰器

在声明式UI中,是以状态驱动视图更新:
在这里插入图片描述
状态(state):指驱动视图更新的数据(被装饰器标记的变量)
视图(View):基于UI描述渲染得到用户界面

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
      Text(this.message)
      .onClick(()=>{
        this.message == 'Hello World'?this.message = '你好 世界':this.message = 'Hello World'
      })
  }
  
}
说明:
@State装饰器标记的变量必须初始化,不能为空值。
@State支持Object、class、string、number、boolean、enum类型已经这些类型的数组。
嵌套类型以及数组中的对象属性无法触发视图更新。

如果做过vue开发应该很好理解。

下个目录所需要的案例

// 任务类
class Task{
  static id:number = 1
  // 任务名称
  name:string  = `任务${Task.id++}`
  // 任务状态:是否完成
  finished:boolean = false
}
// 统一的卡片样式
@Styles function  card(){
  .width('95%')
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  .shadow({radius:6,color:'#1F000000',offsetX:2,offsetY:4})
}
// 任务完成样式
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough})
  .fontColor('#B1B2B1')
}


@Entry
@Component
struct PropPage {
  @State message: string = 'Hello World'
  // 总任务数量
  @State totalTask:number = 0
  // 已完成任务数量
  @State finishTask:number = 0
  // 任务数组
  @State tasks:Task[] = []

  handleTaskChange(){
    // 更新任务总数量
    this.totalTask = this.tasks.length
    // 更新已完成任务数量
    this.finishTask = this.tasks.filter(item => item.finished).length
  }

  build() {
    Column({space:10}) {
      // 任务进度卡片
      Row(){
        Text('任务进度:')
          .fontSize(30)
          .fontWeight(FontWeight.Bold)
        // 层叠容器
        Stack(){
          Progress({
            value:this.finishTask,
            total:this.totalTask,
            type:ProgressType.Ring
          })
            .width(100)
          Row(){
            Text(this.finishTask.toString())
              .fontColor('#36D')
              .fontSize(24)
            Text(' / '+this.totalTask.toString())
              .fontSize(24)
          }
        }

      }
      .card()
      .margin({top:20,bottom:10})
      .justifyContent(FlexAlign.SpaceEvenly)
      // 新增任务按钮
      Button('新增任务')
        .width(200)
        .onClick(()=>{
          this.tasks.push(new Task())
          // 更新任务总数量
          // this.totalTask = this.tasks.length
          this.handleTaskChange()
        })
      // 任务列表

      // 任务列表List版本
      List({space:10}){
        ForEach(
          this.tasks,
          (item:Task,index) =>{
            ListItem(){
              Row(){
                Text(item.name)
                  .fontSize(20)
                Checkbox()
                  .select(item.finished)
                  .onChange(val=>{
                    // 更新当前任务状态
                    item.finished = val
                    // 更新已完成任务数量
                    // this.finishTask = this.tasks.filter(item => item.finished).length
                    this.handleTaskChange()
                  })
              }
              .card()
              .justifyContent(FlexAlign.SpaceBetween)
            }
            .swipeAction({end:this.DeleteButton(index)})
          }
        )
      }
      .width('100%')
      .alignListItem(ListItemAlign.Center)
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F2F3')
  }

  @Builder DeleteButton(index: number){
    Button(){
      Image($r('app.media.ic_public_delete_filled'))
        .fillColor(Color.White)
        .width(20)
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .backgroundColor(Color.Red)
    .margin(5)
    .onClick(()=>{
      this.tasks.splice(index,1)
      this.handleTaskChange()
    })
  }
}

5.2 @Prop和@Link

状态管理
当父子组件之间需要数据同步时,可以使用@Prop和@Link装饰器:

@Prop@Link
同步类型单向同步双向同步
允许修饰的变量类型1. @Prop只支持string、number、boolean、enum类型 。2.父组件对象类型,子组件对象属性。3.不可以是数组、any1.父子类型一致:string、number、boolean、enum、object、class,以及他们的数组。2.数组中元素增、删、替换会引起刷新。 3.嵌套类型以及数组中的对象属性无法触发视图更新
初始化方式不允许子组件初始化父组件传递,禁止子组件初始化

在这里插入图片描述

// 任务类
class Task{
  static id:number = 1
  // 任务名称
  name:string  = `任务${Task.id++}`
  // 任务状态:是否完成
  finished:boolean = false
}
// 统一的卡片样式
@Styles function  card(){
  .width('95%')
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  .shadow({radius:6,color:'#1F000000',offsetX:2,offsetY:4})
}
// 任务完成样式
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough})
  .fontColor('#B1B2B1')
}


@Entry
@Component
struct PropPage {
  @State message: string = 'Hello World'
  // 总任务数量
  @State totalTask:number = 0
  // 已完成任务数量
  @State finishTask:number = 0




  build() {
    Column({space:10}) {

      // 任务进度卡片
      TaskStatistics({finishTask:this.finishTask,totalTask:this.totalTask})

      // 任务列表
      TaskList({finishTask:$finishTask,totalTask:$totalTask})


    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F2F3')
  }


}


@Component
struct TaskStatistics {
  @Prop finishTask:number
  @Prop totalTask:number


  build(){
    Row(){
      Text('任务进度:')
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
      // 层叠容器
      Stack(){
        Progress({
          value:this.finishTask,
          total:this.totalTask,
          type:ProgressType.Ring
        })
          .width(100)
        Row(){
          Text(this.finishTask.toString())
            .fontColor('#36D')
            .fontSize(24)
          Text(' / '+this.totalTask.toString())
            .fontSize(24)
        }
      }

    }
    .card()
    .margin({top:20,bottom:10})
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}


@Component
struct TaskList {

  @Link finishTask:number
  @Link totalTask:number
  // 任务数组
  @State tasks:Task[] = []
  handleTaskChange(){
    // 更新任务总数量
    this.totalTask = this.tasks.length
    // 更新已完成任务数量
    this.finishTask = this.tasks.filter(item => item.finished).length
  }
  build(){
    Column(){
      // 新增任务按钮
      Button('新增任务')
        .width(200)
        .onClick(()=>{
          this.tasks.push(new Task())
          // 更新任务总数量
          // this.totalTask = this.tasks.length
          this.handleTaskChange()
        }).margin({bottom:10})

      // 任务列表List版本
      List({space:10}){
        ForEach(
          this.tasks,
          (item:Task,index) =>{
            ListItem(){
              Row(){
                Text(item.name)
                  .fontSize(20)
                Checkbox()
                  .select(item.finished)
                  .onChange(val=>{
                    // 更新当前任务状态
                    item.finished = val
                    // 更新已完成任务数量
                    // this.finishTask = this.tasks.filter(item => item.finished).length
                    this.handleTaskChange()
                  })
              }
              .card()
              .justifyContent(FlexAlign.SpaceBetween)
            }
            .swipeAction({end:this.DeleteButton(index)})
          }
        )
      }
      .width('100%')
      .alignListItem(ListItemAlign.Center)
      .layoutWeight(1)
    }
  }

  @Builder DeleteButton(index: number){
    Button(){
      Image($r('app.media.ic_public_delete_filled'))
        .fillColor(Color.White)
        .width(20)
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .backgroundColor(Color.Red)
    .margin(5)
    .onClick(()=>{
      this.tasks.splice(index,1)
      this.handleTaskChange()
    })
  }
}

5.3 @Provide和@Consume

@Provide和Consume可以跨组件提供类似于@State和@Link的双向同步
在这里插入图片描述

// 任务类
class Task{
  static id:number = 1
  // 任务名称
  name:string  = `任务${Task.id++}`
  // 任务状态:是否完成
  finished:boolean = false
}
// 统一的卡片样式
@Styles function  card(){
  .width('95%')
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  .shadow({radius:6,color:'#1F000000',offsetX:2,offsetY:4})
}
// 任务完成样式
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough})
  .fontColor('#B1B2B1')
}

statInfo{
  // 总任务数量
  totalTask:number = 0
  // 已完成任务数量
  finishTask:number = 0

}

@Entry
@Component
struct PropPage {
	//统计信息
	@Provide state:StatInfo = new StatInfo()


  build() {
    Column({space:10}) {

      // 任务进度卡片
      TaskStatistics()//直接不需要传参

      // 任务列表
      TaskList()//直接不需要传参


    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F2F3')
  }


}


@Component
struct TaskStatistics {
  @Consume stat: StatInfo


  build(){
    Row(){
      Text('任务进度:')
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
      // 层叠容器
      Stack(){
        Progress({
          value:this.StatInfo.finishTask,
          total:this.StatInfo.totalTask,
          type:ProgressType.Ring
        })
          .width(100)
        Row(){
          Text(this.finishTask.toString())
            .fontColor('#36D')
            .fontSize(24)
          Text(' / '+this.totalTask.toString())
            .fontSize(24)
        }
      }

    }
    .card()
    .margin({top:20,bottom:10})
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}


@Component
struct TaskList {

  @Consume stat: StatInfo
  // 任务数组
  @State tasks:Task[] = []
  handleTaskChange(){
    // 更新任务总数量
    this.StatInfo.totalTask = this.tasks.length
    // 更新已完成任务数量
    this.StatInfo.finishTask = this.tasks.filter(item => item.finished).length
  }
  build(){
    Column(){
      // 新增任务按钮
      Button('新增任务')
        .width(200)
        .onClick(()=>{
          this.tasks.push(new Task())
          // 更新任务总数量
          // this.totalTask = this.tasks.length
          this.handleTaskChange()
        }).margin({bottom:10})

      // 任务列表List版本
      List({space:10}){
        ForEach(
          this.tasks,
          (item:Task,index) =>{
            ListItem(){
              Row(){
                Text(item.name)
                  .fontSize(20)
                Checkbox()
                  .select(item.finished)
                  .onChange(val=>{
                    // 更新当前任务状态
                    item.finished = val
                    // 更新已完成任务数量
                    // this.finishTask = this.tasks.filter(item => item.finished).length
                    this.handleTaskChange()
                  })
              }
              .card()
              .justifyContent(FlexAlign.SpaceBetween)
            }
            .swipeAction({end:this.DeleteButton(index)})
          }
        )
      }
      .width('100%')
      .alignListItem(ListItemAlign.Center)
      .layoutWeight(1)
    }
  }

  @Builder DeleteButton(index: number){
    Button(){
      Image($r('app.media.ic_public_delete_filled'))
        .fillColor(Color.White)
        .width(20)
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .backgroundColor(Color.Red)
    .margin(5)
    .onClick(()=>{
      this.tasks.splice(index,1)
      this.handleTaskChange()
    })
  }
}

5.4 @Observed和@ObjectLink

@ObjectLink和@Observed装饰器用于在涉及嵌套对象或数组元素为对象的场景中进行双向数据同步

6.页面路由

页面路由是指在应用程序中实现不同页面之间的跳转和数据传递。
  • 页面栈的最大容量上限为32个页面,使用router.clear()方法可以清空页面栈,释放内存。
  • Router有两种页面跳转模式,分别是:
模式作用
router.pushUrl()目标页不会替换当前页,而是压入页面栈,因此可以用router.back()返回当前页
router.replaceUrl()目标页替换当前页,当前页会被销毁并释放资源,无法返回当前页
  • Router有两种页面实例模式,分别是:
模式作用
Standard标准实例模式。每次跳转都会新建一个目标页并压入栈顶。默认模式。
single单实例模式。如果目标页已经存在栈中,则离栈顶最近的相同Url页面会被移动到栈顶并重新加载

使用步骤
1.导入组件,Router模块:

import router from '@ohos.router';

2.利用router实现跳转、返回等操作:

//跳转到指定路径,并传递参数
router.pushUrl(
	{
		url:'pages/ImagePage',//目标页面路径
		params:{id:1}//传递参数(可选)
	},
	router.RouterMode.Single,//页面模式:RouterMode枚举
	err => {
		if(err){
			//异常响应回调函数,错误码err.code:
			//100001:内部错误,可能是渲染失败
			//100002:路由地址错误
			//100003:路由栈中页面超过32
			console.log('路由失败.')
		}
	}
)

//获取传递过来的参数
params: any = router.getParams()

//返回上一页
router.back()

//返回到指定页,并携带参数
router.back(
	{
		url:'pages/Index',
		params:{id:10}
	}
)
  • 62
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值