鸿蒙语言基础
准备工作
去鸿蒙官网下载开发环境
点击右侧预浏览,刷新和插销按钮,插销表示热更新,常用按钮。
基础语法
string number boolean const常量 数组
let s : string = "1111";
console.log("string", s);let n : number = 1;
console.log("number", n);let bool : boolean = true;const PI= "asdfasdf";
console.log(PI);let numbers = [1, 2, 3, 4, 5, 6];
console.log("arr", numbers);
接口
实现接口时,必须实现所有的属性和方法
interface HI{a : string;b : number;c : boolean;sing : (song:string) => void;dance : ()=>void;
}let person: HI = {a : "123",b : 1,c : true,sing : (song:string)=>{console.log("唱首歌", song);},dance : ()=>{}
}
console.log("1", person.a, person.b, person.c);
person.sing("爱的供养");
function fun(){}
联合类型
// 1
let judge : number | string = 100;
judge = "A";// 2
let gender : 'man' | 'woman' = 'man';
枚举类型
enum ThemeColor {Red = '#ff0f29',Orange = '#ff7110',Green = '#30b30e'
}
let color : ThemeColor = ThemeColor.Red;
字符串拼接
字符串+数字
数字+字符串
字符串+ 字符串
只要一边是字符串就是拼接。
模板字符串
``里面可以使用变量,方便多个字符串的拼接。
数字和字符串转换
需要注意的是:
parseInt('1.1a') 直接取整,忽略0.1a
parseFloat('1.1a') 1.1
parseFloat('1.a1') 1
也就是说,parseFloat在遇到非数字时就会截断。
点击事件
.onClick(),参数为一个回调函数
Button('按钮').onClick(()=>{AlertDialog.show({message : '弹窗'})
})
状态管理
注意:struct里的变量必须用this访问且不能使用let定义。
小技巧:点击预览器上面的T标志,可以使用鼠标定位元素对应的代码。
数组操作
添加:
arr.unshift(); //从开头增加,返回操作后数组长度
arr.push(); //从结尾增加,返回操作后数组长度
删除:
arr.shift(); //从开头删除,返回删除的项
arr.poll(); //从结尾删除,返回删除的项
在指定位置增加/删除n个元素:
arr.splce(起始位置, 删除个数, 新增元素1, 新增元素2, ...);
if语句
小括号结果不是布尔类型时,会类型转换为布尔值
if(0、空串、null和undefine)这几种均视为false
其他非空值(如对象)均视为true,如空数组和空对象:if( [] )、if( {} )
for...of
对象数组
不能直接使用对象输出,要使用JSON.stringify(对象);
interface Person {name : string,age : number
}
let arr : Person[] = [{name:"111",age: 1},{name:"222", age: 2}
]
console.log("", arr[1]); //[object Object]
for (let item of arr){console.log(JSON.stringify(item));
}
ForEach—— 渲染控制
注意使用ForEach时,item需要指定类型,index指不定都行,建议写上。
class
类是用于 创建对象 模板。同时类声明也会引入一个 新类型,可定义其 实例属性、方法 和 构造函数。
一般定义更加复杂的类型时就不适用接口了而使用Class。
1、实例属性:在定义class时必须赋初值,或者使用可选链操作符 ?. 来定义属性
2、不同实例,将来需要有不同的字段初始值,就需要通过构造函数实现
构造函数使用关键字:constructor 来定义,在new对象时调用。如果参数多可是传一个对象,这样可以自由顺序赋值。
3、方法:方法的返回值可以写在函数名之后,用冒号隔开,即:这个函数的类型时返回值类型的。
4、静态属性、方法:一般用作工具属性方法,用类名直接调用。
interface IFood {name : string,price : number,desc : string
}class Food {// 1、属性name : stringprice : numberdesc : stringa ?: number// 2、构造constructor(mesObj:IFood) {this.name = mesObj.namethis.price = mesObj.pricethis.desc = mesObj.desc}// 3、方法sayHi(name:string):void{console.log(this.name, name);}// 4、静态属性、方法static num:numberstatic func(){}
}
5、继承extend和super关键字
类可以通过 继承 快速获取另外一个类的 字段 和 方法。只支持单一继承。
子类通过 super 可以访问父类的实例字段、实例方法和构造函数。
super.属性
super.方法
super(1, 2) //调用父类构造
6、instanceof 类型检测
实例对象 instanceof 类型
typeof 表达式 : 只能检测简单类型,对象类型结果均为Object。
7、修饰符
ArkUI
构建页面思路:排版 -> 内容 -> 美化
一般先设置Column为列,Row为行。这两个均为容器组件。
build的最外层只能有一个容器组件,也就是root节点(只能有一个根节点)
设置居左:Column和Row都设置width('100%')
struct Index {@State message: string = 'Hello World';build() {Column(){ //build的最外层只能有一个容器组件,也就是root节点;容器组件//Text为基础组件Text("小说简介").width('100%').fontSize(20).fontWeight(FontWeight.Bold).backgroundColor(Color.Grey).height(40)Row(){Text("都市").width(50).height(30).backgroundColor(Color.Orange)Text("生活").width(50).height(30).backgroundColor(Color.Pink)Text("情感").width(50).height(30).backgroundColor(Color.Yellow)Text("男频").width(50).height(30).backgroundColor(Color.Red)}.width('100%')}.width('100%')}
}
显示页面
文字色值写法:2种
文字溢出省略、行高
注意:textOverflow需要传一个对象进去,可以使用lineHeight设置行高。
Text('12345678901234567890123456789012345678901234567890' +'12345678901234567890123456789012345678901234567890').textOverflow({overflow:TextOverflow.Ellipsis}).maxLines(2).lineHeight(30)
图片组件
给图片设置一致的宽高比:.aspectRatio(2.4) 宽 / 高
输入框与按钮
调整组件之间的间隙:Column({space:10})
Column({space:10}){TextInput({placeholder:'用户名'})TextInput({placeholder:'密码'}).type(InputType.Password)Button('登录').width(200)
}
显示展示:
登录案例
使用column.width('100%')使图片居中;
使用column.padding(20)调整内边距;
使用Column({space : 20}) 和 Row({space : 20})调整元素之间距离。
build() {Column({space:20}){Image($r('app.media.app_icon')).width(80)TextInput({placeholder : "请输入用户名"})TextInput({placeholder : "请输入密码"}).type(InputType.Password)Button("登录").width('100%')Row({space:15}){Text("前往注册")Text("忘记密码")}}.width('100%').padding(20)
svg图标
任易放大缩小不失真,可以改颜色。
可以使用官方的图标库进行下载:鸿蒙图标库
https://developer.huawei.com/consumer/cn/design/harmonyos-icon/
布局元素(盒子模型)
margin - border - padding
传参数{space : 1}也可是设置外边距,但是只能设置统一值,margin可以单独设置;
如果值统一,可以直接设置数值,如果不统一,可以传对象;
border样式有三种:实线、虚线、点线。
build() {Column(){Text('刘备').backgroundColor(Color.Gray).padding(20).margin(20).border({width : 3,color : Color.Blue,style : BorderStyle.Dotted})Text('关羽').backgroundColor(Color.Orange).padding(20).margin(20).border({width : {left:1, top:2, right:3, bottom:4},color : { left:Color.Blue, top:Color.Brown, right:Color.Green, bottom:Color.Red },style : BorderStyle.Solid})Text('张飞').backgroundColor(Color.Pink).padding({left : 20,top : 20,right : 20,bottom : 20}).margin(20)}}
设置圆角
Text('刘备').backgroundColor(Color.Gray).padding(20).margin(20).border({width : 3,color : Color.Blue,style : BorderStyle.Dotted
}).borderRadius(30).borderRadius({topLeft:10, topRight:20, bottomLeft:30, bottomRight:40})
正圆:width、height均为100,圆角设置为50。
胶囊按钮:width为100,height为50,圆角设置为25。
背景属性
图片:
.backgroundImage($r('app.media.startIcon'))//可以使用一个参数
.backgroundImage($r('app.media.startIcon'), ImageRepeat.XY) //两个参数可以设置平铺
位置:
其中的100是虚拟像素,vp。对于不同设备会自动转换,保证不同设备视觉效果一致(推荐)。
可以使用vp2ps()转换,但是现在可能已经直接使用了,不需要转换。
大小(缩放):
组件排布(对齐)——线性布局
justifyContent(FlexAlign.Center);
个人中心元素对齐案例:
交叉轴
对齐方式:
案例:既用到主轴对齐,有用到交叉轴对齐。
自适应伸缩.layoutWeight
按照份数权重,分配剩余空间。
layoutWeight(1),1表示在剩余的空间里占一份,不需要自适应的设置一个固定值即可。
build() {Column(){Row(){Text("1").height(100).backgroundColor(Color.Brown).layoutWeight(1)Text("2").width(100).height(100).backgroundColor(Color.Gray).layoutWeight(1)Text("3").width(100).height(100).backgroundColor(Color.Pink)}}}
弹性布局
上图中123和线性布局基本一样,重点在4.布局换行中使用弹性布局。
单行或者单列的情况,还是优先使用线性布局(线性布局底层就是根据Flex去设计的。),而且还做了性能优化。
Flex布局:伸缩布局。当子盒子的总和溢出父盒子,默认进行压缩显示。
适用的情况:如上图阶段选择案例,多行且不规则排列的场景。
Flex是伸缩布局:
设置wrap后:
绝对定位和层级.position
默认后面的元素层级高于前面的元素,可以使用zIndex调整层级,使用zIndex时其他元素默认为0级。
层叠布局
小技巧:使用Ctrl+p在参数传对象时,可以直接看到对象的参数类型。
在使用绝对定位比较麻烦的时候,可以使用层叠布局,使得代码更简洁。
弹簧组件Blank
Blank()在两个组件之间添加,撑开中间的空间。
Badge角标组件
用Badge包裹在需要角标的组件外。
Badge组件只能将角标放在右上、中左、中右三个位置,其他位置需要角标可以使用绝对定位来做。
网格布局Grid
GridItem中只能有且只有一个子元素,即代码中的Column;
1fr调整分几份;
Gap调整中间的间隙。
图中的左边缝隙最大,是视觉效果,图片放大后并无差异。
蒙层设置
使用层叠布局Stack,点击立即抽卡,提高蒙层的zIndex。设置透明度和动画缩放。
抽卡完整功能代码
注意随机抽卡中,修改对象数组中对象的某个值,需要修改整个对象,即arr[index] = {},重新传入一个对象,这是因为监听一个变量消耗的性能很高,对象中的数据很多的话会浪费性能。
在验证是否集齐6张卡片的时候,可以使用假设成立法,for之前定义一个flag,for中count均>0那么修改flag,最后给外部的isget(获得大奖)变量赋值。
// 定义接口 (每个列表项的数据结构)
interface ImageCount {url: stringcount: number
}// 0 1 2 3 4 5
// [0,1) * 6 => [0,6)
// 求随机数: Math.random
// 向下取整: Math.floor
// console.log('随机数', Math.floor(Math.random() * 6))@Entry
@Component
struct Index {// 随机的生肖卡序号 0-5@State randomIndex: number = -1 // 表示还没开始抽// 基于接口, 准备数据@State images: ImageCount[] = [{ url: 'app.media.bg_00', count: 0 },{ url: 'app.media.bg_01', count: 0 },{ url: 'app.media.bg_02', count: 0 },{ url: 'app.media.bg_03', count: 0 },{ url: 'app.media.bg_04', count: 0 },{ url: 'app.media.bg_05', count: 0 }]// 控制遮罩的显隐@State maskOpacity: number = 0 // 透明度@State maskZIndex: number = -1 // 显示层级// 控制图片的缩放@State maskImgX: number = 0 // 水平缩放比@State maskImgY: number = 0 // 垂直缩放比// 控制中大奖遮罩的显隐@State isGet: boolean = false@State arr: string[] = ['pg', 'hw', 'xm'] // 奖池@State prize: string = '' // 默认没中奖build() {Stack() {// 初始化的布局结构Column() {Grid() {ForEach(this.images, (item: ImageCount, index: number) => {GridItem() {Badge({count: item.count,position: BadgePosition.RightTop,style: {fontSize: 14,badgeSize: 20,badgeColor: '#fa2a2d'}}) {Image($r(item.url)).width(80)}}})}.columnsTemplate('1fr 1fr 1fr').rowsTemplate('1fr 1fr').width('100%').height(300).margin({ top: 100 })Button('立即抽卡').width(200).backgroundColor('#ed5b8c').margin({ top: 50 }).onClick(() => {// 点击时, 修改遮罩参数, 让遮罩显示this.maskOpacity = 1this.maskZIndex = 99// 点击时, 图片需要缩放this.maskImgX = 1this.maskImgY = 1// 计算随机数 Math.random() [0,1) * (n + 1)this.randomIndex = Math.floor(Math.random() * 6)})}.width('100%').height('100%')// 抽卡遮罩层 (弹层)Column({ space: 30 }) {Text('获得生肖卡').fontColor('#f5ebcf').fontSize(25).fontWeight(FontWeight.Bold)Image($r(`app.media.img_0${this.randomIndex}`)).width(200)// 控制元素的缩放.scale({x: this.maskImgX,y: this.maskImgY}).animation({duration: 500})Button('开心收下').width(200).height(50).backgroundColor(Color.Transparent).border({ width: 2, color: '#fff9e0' }).onClick(() => {// 控制弹层显隐this.maskOpacity = 0this.maskZIndex = -1// 图像重置缩放比为 0this.maskImgX = 0this.maskImgY = 0// 开心收下, 对象数组的情况需要更新, 需要修改替换整个对象// this.images[this.randomIndex].count++this.images[this.randomIndex] = {url: `app.media.img_0${this.randomIndex}`,count: this.images[this.randomIndex].count + 1}// 每次收完卡片, 需要进行简单的检索, 判断是否集齐// 需求: 判断数组项的count, 是否都大于0, 只要有一个等于0,就意味着没集齐let flag: boolean = true // 假设集齐// 验证是否集齐for (let item of this.images) {if (item.count == 0) {flag = false // 没集齐break // 后面的没必要判断了}}this.isGet = flag// 判断是否中奖了, 如果是 需要抽奖if (flag) {let randomIndex: number = Math.floor(Math.random() * 3)this.prize = this.arr[randomIndex]}})}.justifyContent(FlexAlign.Center).width('100%').height('100%')// 颜色十六进制色值,如果是八位,前两位,就是透明度.backgroundColor('#cc000000')// 设置透明度.opacity(this.maskOpacity).zIndex(this.maskZIndex)// 动画 animation, 当我们元素有状态的改变,可以添加animation做动画.animation({duration: 200})// 抽大奖的遮罩层if (this.isGet) {Column({ space: 30 }) {Text('恭喜获得手机一部').fontColor('#f5ebcf').fontSize(25).fontWeight(700)Image($r(`app.media.${this.prize}`)).width(300)Button('再来一次').width(200).height(50).backgroundColor(Color.Transparent).border({ width: 2, color: '#fff9e0' }).onClick(() => {this.isGet = falsethis.prize = ''this.images = [{ url: 'app.media.bg_00', count: 0 },{ url: 'app.media.bg_01', count: 0 },{ url: 'app.media.bg_02', count: 0 },{ url: 'app.media.bg_03', count: 0 },{ url: 'app.media.bg_04', count: 0 },{ url: 'app.media.bg_05', count: 0 }]})}.justifyContent(FlexAlign.Center).width('100%').height('100%').backgroundColor('#cc000000')}}}
}
Swiper轮播组件——轮播图
一、基础用法
切记不要在内层设置尺寸,要在Swiper设置。
二、常用属性
三、自定义属性
自定义圆点,indicator传true/false为打开关闭圆点,前三个设置默认状态下圆点,后三个设置选中状态下圆点。
样式和结构的重用
@Extend:针对组件(样式、事件)进行扩展实现复用效果。
可以传参,只能全局定义。
@Styles: 抽取通用属性、事件 实现复用效果。
不可以传参,可以在struct内编写,此时不用加function
@Builder:自定义构建函数(针对结构、样式、事件进行扩展实现复用)。
可以传参、需要访问内部状态可以在局部定义、可以写结构。
也可以自定义组件来实现,比较简单的可以使用@Builder
可以全局定义,也可以在组件内定义。 如果需要访问内部效果,必须在组件内定义,这样才能通过this访问到自己的状态。
不同的是,不用点,直接写函数,如下图navItem。可以理解为一个轻量的组件封装。
Scroll
一、核心用法
Scroll内部只支持一个子组件。
二、常见属性
Scroll(){}
.scrollable(ScrollDirection.Vertical) //纵向滑动
.scrollBar(BarState.Auto) //on一直显示 off隐藏 auto滑动时显示
.scrollBarColor(Color.Orange) //颜色
.scrollBarWidth(20) //宽度
.edgeEffect(EdgeEffect.Spring) //效果
三、控制器(返回页面顶部、获取滚动距离)
返回页面顶部;获取滚动距离。
三步走:
1、创建scroller对象;
2、将对象和Scroll绑定;
3、this.scroller.scrollEdge(Edge.Top)。 //也可以用start,效果一样
四、事件
案例:超过400显示,反之隐藏。设置一个@state变量存储Y的偏移量,在onscroll中赋值。
if (偏移量 > 400) {
小火箭组件
}
因为添加@state后这个变量就是一个实时变化的值,所以if可以直接写在这里。
Scroll(){}
.onScroll((x, y) => { //滚动时,会一直触发});
TabBar组件
基本用法和属性
barPosition :调整位置 开头 或 结尾 (参数)
vertical :调整导航 是否垂直
scrollable :是否 手势滑动 切换
animationDuration :点击滑动动画时间
@Entry
@Component
struct Index {build() {Tabs({barPosition:BarPosition.End}){TabContent(){Text("首页内容")}.tabBar("首页")TabContent(){Text("推荐内容")}.tabBar("推荐")TabContent(){Text("发现内容")}.tabBar("发现")TabContent(){Text("我的内容")}.tabBar("我的")}.vertical(false).scrollable(true).animationDuration(0)}
}
滚动导航栏
.barMode(BarMode.Scrollable) //BarMode.Fixed 默认值 固定
自定义TabBar(加图片等)
这样可以在自定义的函数中加入图片、结构(column)等。
可以传参数。
高亮切换
监听事件有两个:
点击和滑动都触发:onChange(event: (index: number) => void)
只有点击都触发:onTabBarClick(event: (index: number) => void)
1、通过Tabs(){}.onChange获取index,赋值给外部的selectIndex
2、给自定义TabBar增加参数:index,高亮的图片
3、在自定义TabBar中增加比较语句,与selectIndex相等的话就文字变色,切换高亮图片。
小米有品案例
对于这种中间有特殊结构的,再重新自动以一个TabBar放在中间即可。
自定义组件
1、基本使用
由框架直接提供的称为 系统组件,由开发者定义的称为 自定义组件。
和空项目给出的是一样的,空项目多一个@Entry,可以复制一下直接改名字即可。
使用自定义组件:HelloComponent()
// 定义
@Component
struct HelloComponent {// 状态变量@State message:string =''build(){// .... 描述 UI}
}
2、自定义组件可以使用通用样式、通用事件
HelloComponent().width().onClick()
在单独的文件中写事件,添加export导出,export struct HelloComponent{}
如果想要单独预览组件,可以使用 @Preview 进行装饰
3、状态变量、成员变量(可赋值为函数),外部可传参覆盖
成员函数不可覆盖。
4、@BuilderParam传UI
3中,自定义组件传递文本参数;如果内部结构有所不同那么就不能直接复用,BuilderParam可以传递内部结构。
状态管理-@state
当运行时的 状态变量 变化,带来UI的重新渲染,在ArkUI中统称为 状态管理机制。
变量必须被 装饰器 装饰才可以成为状态变量。
@State自己的状态
注意:不是所有的状态变量改变都会引起界面的刷新的,只有被框架观察到的修改才会引起UI刷新。
1. boolean、string、number类型时,可以观察到数值的变化
2. class或者Object时,可观察 自身的赋值 的变化, 第一层属性赋值的变化,即Object.keys(observedObject.toString()) 返回的属性。
class Car {name:string = ""
}
class Person{name:string = ""car:Car = {name:""}
}@Entry
@Component
struct Index {@State person : Person = {name:'jack',car:{name:'bigCar'}
}build() {Column(){Button("button").onClick(()=>{this.person.car.name = "smallCar"})Text(JSON.stringify(this.person)).fontSize(20)Text(Object.keys(this.person).toString())}}
}
@Prop-父子单向
在使用自定义组件时,子组件想使用父组件的@state变量,只通过传值的方式,当父组件变量变化时,子组件变量值是无法改变的,也就无法重新渲染UI界面。
给子组件中的变量添加@Prop,这样在进行传值时(通过子组件参数),父组件值修改,子组件的值也会修改
如果想要在子组件中修改父组件的值,需要在子组件汇总添加一个函数并由父组件调用赋值,这样这个函数在子组件中调用时,就修改了父组件的@state,但是这样本质上还是在父组件中修改;可以选择在传值时添加一个参数,将这个参数赋值给父组件的@state变量,然后在子组件调用时传参,这样就实现了在子组件中改变父组件@state变量。
父组件中传递的函数要是用箭头函数,因为只有这样this才指向父组件,不然this就会指向子组件。
@Component
struct sonCom {@Prop info:stringchanInfo = (newInfo:string)=>{ //需要通过父组件的函数来修改}build() {Column(){Text(this.info)Button().onClick(()=>{this.chanInfo("son222")})}}
}@Entry
@Component
struct FatherCom {@State info:string = "111"build() {Column(){Text(this.info)Button().onClick(()=>{this.info = "father222"})sonCom({info:this.info,chanInfo:(newInfo:string)=>{ //这里需要的是一个箭头函数,不然this就是子组件的this了// 这里使用了一个小技巧,使得可以再子组件中赋值。this.info = newInfo //如果写成固定值,那么本质上还是在父组件中修改。}}).width('80%').height(200).backgroundColor(Color.Orange)}.width('100%').height(300).backgroundColor(Color.Pink)}
}
@Link双向同步
适应@Link可以实现父组件和子组件的双向同步。
父组件@State变量修改,子组件对应的被@Link修饰的变量也修改;在子组件内修改,父组件变量也会改变。
@Provide 和 @Consume
同@Link一样,数据可以双向联动,而且可以跨层级双向联动。
比如父组件使用@Provide修饰,孙组件中使用@Consume修饰,任意处更改此变量,所有组件中有这个变量的,这个变量值都会改变。
被它们修饰的变量名必须一致。
@Observed 和 @ObjectLink
装饰器仅能观察到第一层的变化。对于多层嵌套的情况,比如对象数组等。
他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。
作用:用于在涉及嵌套对象或数组的场景中进行双向数据同步
注意:@ObjectLink修饰符不能用在Entry修饰的组件中
@Observed只能对class进行装饰,在类定义的时候添加@Observed装饰器。此时这个类实例化出来的所有对象都会被自动添加setter和getter函数,来监视他的状态。
在非Enter修饰的组件中,使用@ObjectLink修饰的对象,可以自动更新。
属性更新的逻辑:当我们@Observed装饰过的数据,属性改变时,就会监听到;遍历依赖它的@ObjectLink包装类,通知数据更新。
如何证明能见听到呢?在带有Enter的父组件中调用函数打印没有带@ObjectLink包装类的变量,值也会改变,只是不更新UI界面。
当带有Enter的父组件中也有这个变量时,因为“@ObjectLink修饰符不能用在Entry修饰的组件中”,所以需要包一层。也就是再自定义一个组件,使用@ObjectLink修饰变量。
路由
页面路由指的是在应用程序中实现不同页面之间的跳转,以及数据传递。
1、创建页面
两种方式:
1、使用page创建页面,可以直接添加配置文件
2、使用ArkTs创建文件,需要在下方的resources文件夹profile文件中main_pages.json添加此文件,这样才能正常使用路由功能。
2、页面跳转和后退
两种方法,还有一个back手动返回。
3、页面栈
页面栈是用来存储程序运行时页面的一种 数据结构,遵循 先进后出 的原则
页面栈的最大容量为 32 个页面
案例:都使用pushUrl,跳转几个页面再使用getLength就是1+n;
如果C和D之间反复跳转,也会计算数量;
使用replaceUrl在CD之间跳转,不会增加页面栈长度。点击返回按钮时,如果上一层是B,那么直接返回B。
4、路由模式
路由提供了两种不同的跳转模式
1. Standard:无论之前是否添加过,一直添加到页面栈【默认常用】
2. Single:如果目标页面已存在,会将已有的最近同url页面移到栈顶【看情况使用】
在第二个参数设置 【路由模式】
router.pushUrl(options, mode)
router.pushUrl({url:"pages/default",params:{username:this.username}
}, router.RouterMode.Single)
5、跳转传参
index中的text : $$this.username,$$是双向绑定。在ArkUI框架中,$$this
是一种特殊的语法符号,主要用于按引用传递当前组件实例的上下文。在代码示例中,$$this.username
的作用是将当前组件(Index
组件)的 @State
变量 username
以引用传递的方式绑定到 TextInput
组件上。
aboutToAppear已进入页面就会执行的函数——声明周期函数(钩子)
const params = router.getParams()获取数据,需要进行类型断言,自定义一个和index中相同的类型,然后就可以使用params.变量获取数据了。这是因为在default中不知道传递过来的数据是什么格式的。
钩子(Hook):在编程中,"钩子"(Hook)是一种通过拦截系统或应用程序的事件、函数调用或消息传递,从而修改或扩展其行为的技术。其核心价值在于允许开发者在不修改原有代码的情况下,插入自定义逻辑,实现对程序行为的监控、增强或重定向。
index页面
import { router } from '@kit.ArkUI'@Entry
@Component
struct Index {@State username : string = ""build() {Column(){Text("Index页面").width(300).height(100).fontSize(30)TextInput({text : $$this.username,placeholder : '请输入用户名'}).height(100).fontSize(30)Button("跳转到默认").width(300).height(100).fontSize(30).onClick(()=>{router.pushUrl({url:"pages/default",params:{username:this.username}}, router.RouterMode.Single)})}.width('100%')}
}
default页面
import { router } from '@kit.ArkUI';
interface ParamsObj {username : string
}
@Entry
@Component
struct Default {@State message:string = '默认页面';@State username:string = "";aboutToAppear(): void {console.log(JSON.stringify(router.getParams()))const params = router.getParams() as ParamsObjthis.username = params.usernameconsole.log("this.username---", this.username)}build() {RelativeContainer() {Text(this.message + this.username).id('DefaultHelloWorld').fontSize($r('app.float.page_text_font_size')).fontWeight(FontWeight.Bold).alignRules({center: { anchor: '__container__', align: VerticalAlign.Center },middle: { anchor: '__container__', align: HorizontalAlign.Center }})Button("back").onClick(()=>{router.back()}).width(300).height(100).fontSize(30)}.height('100%').width('100%')}
}
生命周期
组件 和 页面 在创建、显示、销毁的这一整个过程中,会自动执行 一系列的【生命周期钩子】
其实就是一系列的【函数】,让开发者有机会在特定的阶段运行自己的代码
区分 页面 和 组件:@Entry
aboutToAppear:创建组件实例后执行,可以修改状态变量
aboutToDisappear:组件实例销毁前执行,不允许修改状态变量
onPageShow:页面每次显示触发(路由过程、应用进入前后台)
onPageHide:页面每次隐藏触发(路由过程、应用进入前后台)
onBackPress:点击返回触发(return true 阻止返回键默认返回效果)
仅@Entry修饰的页面组件生效
下面的两个案例下载了一起,分别说明一下:
一、点击切换子组件显示控制子组件的显示。默认是显示的,所以输出顺序为:(只写了aboutToAppear和aboutToDisappear两个)
Index - aboutToAppear SonCom - aboutToAppear
再次点击输出:SonCom - aboutToDisappear
二、点击跳转页面跳转到登录页面,登录页面里有一个登录子组件。
初始化后显示:Index - aboutToAppear
点击“跳转页面”后显示:
Login - aboutToAppear
LoginSon - aboutToAppear
Login - onPageShow
点击返回按钮后:
Login - onPageHide
Login - aboutToDisappear
LoginSon - aboutToDisappear
这里需要注意的是,跳转到Login时先创建组件实例,再创建子组件实例,再显示页面。
back时Login页面先隐藏,组件实例销毁函数被调用,此时发现还有子组件,所以先销毁子组件,所有出现了点打印Login的aboutToDisappear后打印LoginSon的aboutToDisappear的情况。
Index页面
import { router } from '@kit.ArkUI'@Component
struct SonCom {aboutToAppear(): void {console.log("SonCom - aboutToAppear")}aboutToDisappear(): void {console.log("SonCom - aboutToDisappear")}build() {Column(){Text("我是子组件")}.width(200).height(200).border({width:3}).margin(20)}
}@Entry
@Component
struct Index {@State show:boolean = trueaboutToAppear(): void {console.log("Index - aboutToAppear")}aboutToDisappear(): void {console.log("Index - aboutToDisappear")}build() {Column(){Text("组件生命周期").fontSize(40)Button("切换子组件显示").onClick(()=>{this.show = !this.show})if (this.show){SonCom()}Button("跳转页面").onClick(()=>{router.pushUrl({url:"pages/Login"})})}}
}
Login页面
import { router } from '@kit.ArkUI';
@Component
struct LoginSon {aboutToAppear(): void {console.log("LoginSon - aboutToAppear")}aboutToDisappear(): void {console.log("LoginSon - aboutToDisappear")}onPageShow(): void {console.log("LoginSon - onPageShow")}onPageHide(): void {console.log("LoginSon - onPageHide")}build() {}
}
@Entry
@Component
struct Login {aboutToAppear(): void {console.log("Login - aboutToAppear")}aboutToDisappear(): void {console.log("Login - aboutToDisappear")}onPageShow(): void {console.log("Login - onPageShow")}onPageHide(): void {console.log("Login - onPageHide")}onBackPress(): boolean | void {// 自己手写返回的代码,将来定制返回的逻辑router.back()}build() {Row(){Text("登录").fontSize(50)LoginSon()}}
}
相关文章:
鸿蒙语言基础
准备工作 去鸿蒙官网下载开发环境 点击右侧预浏览,刷新和插销按钮,插销表示热更新,常用按钮。 基础语法 string number boolean const常量 数组 let s : string "1111"; console.log("string", s);let n : number …...
每天一道C语言精选编程题之字符串拷贝
题目描述 写⼀个函数my_strcpy,实现拷⻉字符串的功能,假设给定⼀个字符数组a,再给定⼀个字符数组b,将字符串a中的内容拷⻉到字符串b中,拷⻉内容包含字符串末尾的 \0 字符。 解法思路 使⽤ while 循环通过指针的⽅式逐…...
C#中扩展方法和钩子机制使用
1.扩展方法: 扩展方法允许向现有类型 “添加” 方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像实例方法一样进行调用。 使用场景: 1.当无法修改某个类的源代码&#…...
基于CNN与VGG16的图像识别快速实现指南
基于CNN与VGG16的图像识别快速实现指南 以下是从零实现代码到原理剖析的完整流程,包含TensorFlow/Keras框架的代码示例与关键优化技巧,满足快速实验需求。 一、核心原理对比 特性CNN(基础模型)VGG16结构深度5-10层(如…...
中间件--ClickHouse-9--MPP架构(分布式计算架构)
1、MPP 架构基础概念 MPP(Massively Parallel Processing 大规模并行处理) 是一种分布式计算架构,专门设计用来高效处理大规模数据集。在这种架构下*,数据库被分割成多个部分,每个部分可以在不同的服务器节点上并行处理*。这意味着ÿ…...
如何在PDF.js中改造viewer.html以实现PDF的动态加载
在PDF.js中改造viewer.html实现PDF动态加载,需结合参数传递、文件流处理及跨域配置等技术。以下是综合多个技术方案的核心实现步骤: 一、基础参数传递法 1. URL参数动态加载 通过修改viewer.html的URL参数传递PDF路径,适用于静态文…...
Android——动画
帧动画 帧动画就是很多张图片,一帧一帧的播放,形成的一个动画效果。 frame.xml <?xml version"1.0" encoding"utf-8"?> <animation-list xmlns:android"http://schemas.android.com/apk/res/android">&l…...
基于linux 设置无线网卡Monitor模式 sniffer抓包
硬件 TP-WN722N 开源无线网卡 网卡设置成抓包模式,条件是什么? 硬件条件 网卡芯片支持监听模式,外置天线或高增益天线可提升抓包效果驱动与软件条件:正确的驱动程序系统与权限条件 Linux:原生支持(Kali …...
Ubuntu18.04安装Qt5.12
本文介绍了在Ubuntu18.04环境下安装QT QT5.12相关安装包下载地址 https://download.qt.io/archive/qt/5.12/ Linux系统下Qt的离线安装包以.run结尾 (sudo apt-get install open-vm-tools open-vm-tools-desktop解决无法paste的问题) 安装 1.cd命令 终端进入对应的文件夹下面 2.…...
克服储能领域的数据处理瓶颈及AI拓展
对于储能研究人员来说,日常工作中经常围绕着一项核心但有时令人沮丧的任务:处理实验数据。从电池循环仪的嗡嗡声到包含电压和电流读数的大量电子表格,研究人员的大量时间都花在了提取有意义的见解上。长期以来,该领域一直受到对专…...
PDF.js 生态中如何处理“添加注释\添加批注”以及 annotations.contents 属性
我们来详细解释一下在 PDF.js 生态中如何处理“添加注释”以及 annotations.contents 属性。 核心要点:PDF.js 本身主要是阅读器,不是编辑器 首先,最重要的一点是:PDF.js 的核心库 (pdfjs-dist) 主要设计用于解析和渲染…...
L38.【LeetCode题解】四数之和(双指针思想) 从汇编角度分析报错原因
目录 1.题目 2.分析 去重的代码 错误代码 3.完整代码 提交结果 1.题目 四数之和 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元…...
【第48节】探究汇编使用特性:从基础到混合编程
目录 引言 一、调用约定的奥秘 1.1 . C调用约定(_cdecl) 1.2 stdcall调用约定(_stdcall) 1.3 fastcall快速调用约定(_fastcall) 1.4 thiscall调用约定(C类成员函数) 二、X64汇…...
【jenkins】首次配置jenkins
第一步,输入管理员密码 cat /var/jenkins_home/secrets/initialAdminPassword第二步,点击安装推荐的插件 第三步,创建管理员用户 第四步,返回实例 第五步, 升级jenkins 第六步, 修复提示 第七步,…...
Python 项目文档编写全攻略:从入门到自动化维护
引言 在软件开发领域,完善的文档可提升 40% 的团队协作效率(来源:IEEE 2022 年开发者调查报告 ^^1^^)。本文将深入探讨 Python 项目文档的最佳实践,涵盖文档生成工具、注释规范、自动化维护等关键环节。 一、Python 文…...
基于 React 和 CodeMirror 实现自定义占位符编辑器
npm git 在前端开发中,我们经常需要实现各种复杂的编辑器功能,比如代码编辑器、富文本编辑器等。本文将介绍如何基于 React 和 CodeMirror 实现一个带有自定义占位符功能的编辑器,这种编辑器在模板系统、表单设计器等场景中非常有用。 一…...
GitHub Copilot在产品/安全团队中的应用实践:处理Markdown、自动化报告与电子表格、使用CLI命令等
本文来源github.com,由GitHub中国授权合作伙伴-创实信息翻译整理。 在当今的快节奏时代,技术和非技术团队之间的协作至关重要,事实证明,GitHub Copilot等工具已成为不可或缺的助手。这些由AI驱动的工具已不只是开发者的“秘密武器…...
嵌入式系统中Flash操作全面解析与最佳实践
嵌入式系统中Flash操作全面解析与最佳实践 一、Flash存储器基础与分类 Flash存储器是嵌入式系统中最重要的非易失性存储介质,根据内部架构和工作原理主要分为两大类: 1.1 NOR Flash与NAND Flash对比 特性NOR FlashNAND Flash架构随机存取架构串行存取…...
tomcat 的安装与启动
文章目录 tomcat 服务器安装启动本地Tomcat服务器 tomcat 服务器安装 https://tomcat.apache.org/下载 Tomcat 10.0.X 启动本地Tomcat服务器 进入 Tomcat 的 bin...
Flash存储器(二):SPI NAND Flash与SPI NOR Flash
目录 一.存储架构 二.接口与封装 三.特性对比 四.典型应用场景 4.1 SPI NOR Flash 4.2 SPI NAND Flash 五.技术演进与市场趋势 六.选择建议 6.1 选择SPI NOR的场景 6.2 选择SPI NAND的场景 SPI NAND Flash和SPI NOR Flash是嵌入式设备中常用的存储器。下面通过全面对…...
第 7 期:DDPM 采样提速方案:从 DDPM 到 DDIM
本期关键词:采样加速、DDIM 推导、可控性提升、伪逆过程、代码实战 前情回顾:DDPM 的采样瓶颈 在前几期中,我们构建了一个完整的 DDPM 生成流程。但是你可能已经发现: 生成一张图像太慢了!!! 原因是: DDPM 要在 T 个时间步中一步步地去噪,从 x_T → x_0。而通常 T 至…...
axios 模拟实现
axios 模拟实现 包含[发送请求,拦截器,取消请求] 第一步 , axios模拟发送请求 //使用 xhr 发送请求function xhr_adpter(config){return new Promise(function handle(resolve,reject){let xhr new XMLHttpRequest();xhr.open(config.method, config.url,true);xhr.onreadys…...
架构师面试(三十一):IM 消息收发逻辑
问题 今天聊一下 IM 系统最核心的业务逻辑。 在上一篇短文《架构师面试(三十):IM 分层架构》中详细分析过,IM 水平分层架构包括:【入口网关层】、【业务逻辑层】、【路由层】和【数据访问层】;除此之外&a…...
hadoop三大组件的结构及各自的作用
1 HDFS 1.1功能 HDFS 是 Hadoop 的分布式文件系统,用于存储和管理海量数据。它具有高容错性、高吞吐量和可扩展性,能够在多个节点上存储和管理大规模数据 1.2架构:采用主从架构,由一个 NameNode 和多个 DataNode 组成。NameNode…...
GEE学习笔记 29:基于GEE的多源Landsat合成与植被指数时序提取
基于GEE的多源Landsat合成与植被指数时序提取 🌿 1.写在前面 | 基于GEE的Landsat多尺度植被指数提取脚本📌 2.常用植被指数计算公式2.1. 🌿 NDVI(归一化植被指数)Normalized Difference Vegetation Index2.2. 🌱 EVI(增强型植被指数)Enhanced Vegetation Index2.3.…...
负载均衡的策略
目的:将请求均衡分发到后台的服务器 算法: 随机算法:随机数获取服务器加权随机算法:根据权重,增加某些服务器(性能比较好等)选择的随机比例轮询算法:轮流分发给服务器加权轮询算法…...
AWS Elastic Beanstalk的部署Python Flask后端服务(Hello,World)
问题 最近需要使用AWS Elastic Beanstalk来部署Python的Flask后端web接口。这里先做一个最简单的Flask Hello,World接口服务程序。 Flask工程与代码 创建本地虚拟环境 conda create -n flask python3.13 # 激活 conda activate flaskapp.py from flask import …...
Hadoop的三大结构及各自的作用?
1.HDFS 作用: 存储海量数据,支持高容错(数据自动备份)和高吞吐量(适合大文件读写)。 采用主从架构: NameNode:管理文件系统的元数据(如文件目录结构)。 Dat…...
在Ubuntu系统中安装和升级RabbitVCS
在Ubuntu系统中安装和升级RabbitVCS 目前在ubuntu中使用svn的GUI工具,已经安装了。想升级一下。 当前遇到的问题是,我想用它看看我当前的代码对应的版本号,然后再决定是否update。但是,好像我看不出来。根本不如在windows使用To…...
深入理解红黑树:原理、实现与应用
深入理解红黑树:原理、实现与应用 引言 红黑树(Red-Black Tree)是计算机科学中一种重要的自平衡二叉查找树。它通过简单的规则和高效的调整策略,保证了插入、删除、查找等操作的时间复杂度均为 O(log n)。红黑树广泛应用于实际开…...
Java学习手册:Java并发编程最佳实践
在Java并发编程中,遵循最佳实践可以显著提高程序的性能、可靠性和可维护性。本文将总结Java并发编程中的关键最佳实践,帮助开发者避免常见陷阱并编写高效的并发程序。 1. 选择合适的并发工具 Java提供了丰富的并发工具,选择合适的工具可以简…...
接口自动化测试(二)
一、接口测试流程:接口文档、用例编写 拿到接口文档——编写接口用例以及评审——进行接口测试——工具/自动化框架进行自动化用例覆盖(70%)——输出测试报告 自动化的目的一般是为了回归 第一件事情:理解需求,学会看接口文档 只需要找到我…...
C++类和对象上
1. 面向对象编程与面向过程编程的比较 我们一开始接触的C语言就是一门面向过程编程的语言,而C就是一门面向对象编程的语言。那么这两者有什么区别呢? 举个例子,就比如说点外卖,如果是C语言的话,那么在程序的编写过程…...
hadoop的三大结构及各自的作用
Hadoop 分布式文件系统(HDFS) 存储大量数据:HDFS 被设计用于在商品硬件上存储海量数据,它将大文件分割成多个数据块,并分布存储在集群中的不同节点上,支持数据的可靠存储和高效访问。提供数据冗余和容错机制…...
珈和科技遥感赋能农业保险创新 入选省级卫星应用示范标杆
为促进空天信息与数字经济深度融合,拓展卫星数据应用场景价值,提升卫星数据应用效能和用户体验,加速卫星遥感技术向民生领域转化应用,近日,湖北省国防科工办组织开展了2024年湖北省卫星应用示范项目遴选工作。 经多渠…...
香港服务器CPU对比:Intel E3与E5系列核心区别与使用场景
香港服务器的 CPU 配置(核心数与主频)直接决定了其并发处理能力和数据运算效率,例如高频多核处理器可显著提升多线程任务响应速度。在实际业务场景中,不同负载需求对 CPU 架构的要求存在显著差异——以 Intel E3 和 E5 系列为例,由于两者在性…...
【人工智能】DeepSeek 与 RAG 技术:构建知识增强型问答系统的实战
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 本文深入探讨了如何利用 DeepSeek R1 模型结合检索增强生成(RAG)技术,构建一个高效的知识增强型问答系统。RAG 技术通过结合信息检索与生…...
得佳胜哲讯科技 SAP项目启动会:胶带智造新起点 数字转型新征程
在全球制造业加速向数字化、智能化转型的浪潮中,胶带制造行业正迎来以“自动化生产、数据化运营、智能化决策”为核心的新变革。工业互联网、大数据分析与智能装备的深度融合,正推动胶带制造从传统生产模式向“柔性化生产精准质量控制全链路追溯”的智慧…...
超导体的应用价值:超导磁探测技术开启科技与生活的新变革
科技的飞速发展,带来了一种新型材料的快速应用,那就是超导体材料。超导体的特性,能够为当今社会众多领域带来革命性的变革,也将极大的改变我们现在的生活质量。 超导体的特性 超导体是指在特定温度下的电阻会突然消失,…...
UNION和UNION ALL的主要区别
UNION和UNION ALL的主要区别在于处理重复数据和排序的方式。 UNION和UNION ALL都是SQL语言中用于合并两个或多个SELECT语句结果集的关键字。它们的主要区别如下: 1、对重复结果的处理:UNION在进行表链接后会筛选掉重复的记录,而UNION ALL不会…...
软件项目验收报告模板
软件项目验收报告 一、项目基本信息 项目名称XX智能仓储管理系统开发单位XX科技有限公司验收单位XX物流集团合同签订日期2023年3月15日项目启动日期2023年4月1日验收日期2024年1月20日 二、验收范围 入库管理模块(包含RFID识别、库存预警)出库调度模…...
第五章 SQLite数据库:5、SQLite 进阶用法:JOIN、UNION、TRIGGER、INDEX、ALIAS、INDEXED BY 等模块
一、JOIN:跨表查询的核心机制 1. JOIN 类型总览 JOIN 是连接多个表获取综合信息的关键手段。常见 JOIN 类型如下: INNER JOIN(内连接):仅返回两个表中满足连接条件的行。LEFT OUTER JOIN(左连接…...
中间件--ClickHouse-10--海量数据存储如何抉择ClickHouse和ES?
在Mysql数据存储或性能瓶颈时,采用冷热数据分离的方式通常是一种选择。ClickHouse和Elasticsearch(ES)是两个常用的组件,但具体使用哪种组件取决于冷数据的存储目的、查询模式和业务需求等方面。 1、核心对比 (1&…...
JESD204B标准及其在高速AD采集系统中的应用详解
一、JESD204B协议的本质与核心价值 JESD204B是由JEDEC制定的第三代高速串行接口标准(2011年发布),专为解决高速ADC/DAC与FPGA/ASIC间数据传输瓶颈而设计。其核心突破体现在: 速率革命性提升 支持每通道最高12.5Gbps(通…...
给予FLUX更好的控制:FLUX.1-dev-ControlNet-Union-Pro-2.0
Shakker Labs FLUX.1-dev-ControlNet-Union-Pro-2.0 一、模型概述 Shakker Labs发布的FLUX.1-dev-ControlNet-Union-Pro-2.0是一个统一的ControlNet模型,专为FLUX.1-dev模型设计。该模型在前一版本基础上进行了多项改进,包括移除模式嵌入以减小模型尺寸…...
Hadoop的三大结构及其作用?
Hadoop是一个分布式存储和计算框架,其三大核心组件是HDFS(Hadoop Distributed File System)、YARN(Yet Another Resource Negotiator)和MapReduce。它们各自有着重要的作用,共同构成了Hadoop生态系统的基础…...
langgraph框架之初识
1.什么是langgraph? LangGraph 是一个用于构建可控代理的底层编排框架。在AI中,代理也就是执行动作的智能体,也就是agent。使用这个框架可以构建一个可以自由控制的智能执行体,它可以帮我们做许多事情,如下࿱…...
3个实用的脚本
1. Linux 系统清理临时文件脚本 该脚本用于清理系统中 /tmp 目录下超过 7 天的临时文件。 #!/bin/bash# 清理 /tmp 目录下超过 7 天的文件 find /tmp -type f -atime 7 -exec rm -f {} \;# 清理 /var/tmp 目录下超过 7 天的文件 find /var/tmp -type f -atime 7 -exec rm -f {…...
Vue3 Composition API与十大组件开发案例详解
文章目录 一、Vue3核心API解析1.1 Composition API优势1.2 核心API 二、十大组件开发案例案例1:响应式表单组件案例2:动态模态框(Teleport应用)案例3:可复用列表组件案例4:全局状态通知组件案例5࿱…...
万用表判断MOS好坏
无论什么封装,D极一般在正面看的上面,或者焊盘面积最大的一面: 【零】烧个洞的那种,不用量了,一眼损坏 【一】万用表的二极管档位测量 检修:使用万用表的二极管档位,S极接红表笔,黑…...