admin管理员组文章数量:1655505
ArkTs基础入门
文章目录
- 一、 (方舟开发框架)ArkUI介绍
- 二、自定义组件
- 自定义公共变量和枚举
- 三、组件事件及使用
- 分割线
- Text文本
- TextInput文本输入框
- TextArea文本域
- Image图片
- BackgroundImage背景图片
- Button按钮
- Radio 单选框
- Toggle切换按钮
- CheckBox 复/多选框
- Select选中框
- Slider进度滑动组件
- Progress进度条
- Router路径跳转
- 扩展setInterval 与setTimeOut的区别
- 四、盒子模型和布局
- Padding内边距
- Border边框
- borderRadius圆角
- Margin外边距
- Column列
- Row行
- 主轴交叉轴
- Blank自适应拉伸,缩放,延伸 弹簧
- layoutWeight自适应缩放 内容的占比
- Scroll滚动条
- 五、动态元素UI构建
- 页面声明周期
- 组件声明周期
- 页面和组件声明周期顺序
- @Builder局部自定义构建函数:
- @Builder全局自定义构建函数:
- @Builder参数传递
- @BuilderParam占位符、插槽
- @Styles组件样式重用的封装
- @Extend 扩展组件样式
- stateStyles多态样式
- Flax弹性布局
- position()绝对定位
- offset()偏移
- Z序控制 : zIndex(数字)
- ForEache用法、数组
- LazyForEach(懒加载)用法、数组
- Stack()堆叠布局
- Grid()网格布局
- 六、UI的渲染控制
- Math对象
- If(){}else{}判断
- ForEach()循环判断
- 七、简单容器组件使用
- 7.1 通用属性
- linearGradient()颜色渐变效果 :线性渐变==线性
- radialGradient()颜色渐变效果 :径向渐变== 圆形
- shadow()阴影效果
- animation动画
- 图形变换
- translate() 平移
- scale() 缩放
- rotate() 旋转
- 7.2 List列表
- 基本使用
- divider分割线属性
- Badge列表标记
- scrollBar滚动条
- ListItemGroup分组列表
- Scroller滚动位置控制
- AlphabetIndexer响应滚动控制
- swipeAction列表事件,左右滑动
- 7.3 滚动Scroll、Scorrer
- Scroll组件
- Scorrer控制器
- 八、Swiper轮播组件
- 九、Tabs组件
- 十、Navigation分栏、标题栏、工具栏,导航栏组件
- 十一、TextPicker文本选择器
- 十二、TextPickerDialog弹框
- 十三、TimePicker选择器
- 十四、TimePickerDialog弹框
- 十五、DatePicker选择器
- 十六、DatePickerDialog弹框
- 十七、自定义选择器 和 CustomDialog自定义弹框
- 十八、AlertDialog警告弹框
- 十九、ActionSheet列表弹框
- 二十、装饰器传值和监听watch
- 二十一、状态存储
- LocalStorage:页面级UI状态存储(局部、全局)
- AppStorage:应用全局的UI状态存储
- PersistentStorage:持久化存储UI状态
- Environment:设备环境查询
- 二十二、手势
- Gesture点击手势
- LongPressGesture长按手势
- PanGesture拖动手势
- PinchGesture捏合手势
- RotationGesture旋转手势
- SwipeGesture滑动手势
- GestureGroup组合手势
- 组合手势案例:(缩放、旋转、拖动)
- 二十三、绘制组件
- Circle圆形
- Ellipse椭圆
- Line线性
- PolyLine折线
- Polygon多边形
- Path路径绘制
- Rect矩形
- Shape父组件
- 二十四、Canvas画布组件
- 二十五、动画
- animation动画
- animateTo显示动画
- Navigator转场动画,可以用于路径跳转
- pageTransition页面转场动画效果
- animateTo组件内动画
- sharedTransition共享元素组件
- motionPath路径动画
- 二十六、多媒体
- Video视频
- 扩展
- 项目启动注意事项或者检查(**会导致模拟启动不起来等其他情况)
- 规范项目结构
一、 (方舟开发框架)ArkUI介绍
方舟开发框架(简称:ArkUI),是一套 构建 HarmonyOS 应用 界面 的框架。构建页面的最小单位就
是 "组件"。
二、自定义组件
自定义组件的构成:
ArkTs通过装饰器:@Component和@Entry装饰struct关键字声明数据结构,构成一个自定义组件。
自定义组件中提供了一个build(){} 函数,须在该函数内进行链式调用的方式进行基本的UI描述
@Entry:@Entry没有页面不会被加载,一个自定义组件只能被一个@Entry进行修饰,也是UI页面的入口
@Component : 表示自定义组件,只能修饰struct关键字声明结构,被修饰后具有组件渲染能力
自定义组件格式:
@Entry
@Component
struct Index {
build(){
}
}
在同一个文件中:定义一个组件可以被实现调用
@Component
struct Index2 {
build(){
}
}
调用方式:
@Entry
@Component
struct Index {
build(){
column(){
Index2()
}
}
}
自定义公共变量和枚举
例:
export const FONT_COLOR: Color = Color.Orange
export const FONT_COLOR_Str: string = "#000"
export const FONT_SIZE: number = 40
export const enum PADDING_SIZE {
TOP = 10,
RIGHT = 10,
BOTTOM= 5,
LEFT = 20
}
三、组件事件及使用
分割线
Divider() 分割线
Text文本
Text("字符串"或者在element中拿取对应值)
格式:
方式一 Text("字符串")
方式二 Text($r("app.string.json文件名.对应name") // 目的为了国际化
Text("值")属性:
.fontSize() 字体大小
.fontWeight() 设置字体粗细,值可以设置为字符串或者数字类型数字的取值在[100,900]默认400
.fontColor() 字体颜色,建议使用十六进制和枚举
.border() 边框 //如:.border({ width: 2 })
.TextAlign(TextAlign.___) 文本Center居中 Start左边 End右边
.decoration({ type: TextDecorationType._____}) 设置 Underline下划线、LineThrough中划线、Overline上划线
.MaxLines(number) 设置最大行数 ,多出的不会显示,若想看是否存在溢出需要结合 textOverflow,但不会显示溢出多少信息只是有个表示。。。
.textOverflow({overflow:TextOverflow.Ellipsis}) Clip溢出不显示,Ellipsis:超出最大行数才会生效,才体现一处效果,MARQUEE: 滚动效果
.lineHeight() 行高 :行与行的高度
.borderRadius(8) 设置圆边框
.opacity(number | Resource) 设置透明度
.letterSpacing(number | string) 设置字体之间的间隙
.width() 宽度
.height() 高度
当Text中写Span后,text是不生效的,样式也是一样
如:
Text(`sssvfvfv`) {
Span("米好") 业务span内容会覆盖Text内容,若样式都有则文本样式不生效
}
TextInput文本输入框
TextInput({ placeholder: '提示信息',text:'默认值' })
.width()宽度
.height() 高度
// 常用事件
.onChange((val)=>{}) 触发事件:当写箭头函数时val位置,可以获取输入变量,用于改变定义变量信息
.onSubmit(()=>{}) 当点击回车,触发执行事件
// 不常用事件
.onFocus(()=>{}) 当获取文本焦点则就会触发
.onBlur(()=>{}) 当失去文本输入框焦点,则会触发
.type(InputType.___) 设置是普通文本、Number数值、Password密码、Email邮箱、PhoneNumber手机号 格式
TextArea文本域
// 多行输入框
// 当一行输入到头时,则自动更新换下一行
TextArea()
Image图片
图片的引用存在4个方式:
1.当文件在media下时,调用方式为: Image($r("app.media.图片名"))
2.当文件在rawfile下时,调用方式为:Image($rawfile("图片名"))
3.pages内可以任意创建文件 使用相对路径 如:Image("./pages/image.png")
4.引用网络资源,
Image("图片访问地址")
需要在module.json5配置网络权限
"module": { // 文件中已经存在
// 添加网络请求权限 固定格式
"requestPermissions": [{"name": "ohos.permission.INTERNET" }]
}
格式及相关属性:
Image("4种方式")
.width("100")
// .height("50")
// 宽高比 同时设置宽高不会使用,
// 设置一个宽或者高然后再设置宽高比 当存在宽高比为长方形则会显示不全
.aspectRatio(1)
.alt("URL路径 4种方式") // 一般是本地,展位图,当引入外来资源,或者加载慢,则会显示展位图
.fillColor("颜色") // 设置图标颜色 [图标库](https://developer.huawei/consumer/cn/design/harmonyos-icon/)
.objectFit(ImageFit.__) // 图片缩放 常用: Fill:按照容器尺寸铺满。Cover:截取一部分 Contain:按照比例展示
.blur() // 模糊度 越大越模糊 10-100
.opacity() // 越小越透明 0-1
BackgroundImage背景图片
例:
Text("背景土")
.width(300)
.height(300)
.backgroundColor(Color.Orange) // 图片背景颜色,一般不用
.backgroundImage("/pages/image.png") // 背景图片
.backgroundImageSize(ImageSize.Contain 或者 {width:280,height:280}) // 背景图片大小 {width:280,height:280}或者ImageSize属性 ImageSize属性:Cover:截取一部分 Contain:按照比例展示
.backgroundImagePosition(Alignment.Center) // 位置坐标位置,但是不是平铺过去 {x:280,y:290} 或者 Alignment属性
.border({ width: 1,radius:0) }) // 边框,边缘圆角
Button按钮
格式:
Button(“名称”,{type: ButtonType.____}) // Circle圆形,Capsule胶囊,Normal矩形
.onClick(()=>{处理业务})点击事件使用
.enabled(boolean) :按钮判断合适禁用启用
Button("登录") // type,可选见上
.width("80%")
.onClick(() => {
if (true) {
AlertDialog.show({ message: '登录成功' })
} else {
AlertDialog.show({ message: '登录失败' })
}
})
.enabled(true) // true启用 false 禁用
Button按钮 还可以存在子组件
Button() {
Row() {
Image("/pages/image.png")
.width(50)
.aspectRatio(2) // 宽高比
}
}
Radio 单选框
Radiod({value:'单选名字',group:'分组'})
.checked(true) // 是否默认 true:默认
.onChang((val)=>{ // 当发生点击,触发的事件,并会传递值
if(val){
// 业务体
}
})
** 当存在多个单选框时,需要弹开,可以使用 Blank() 函数(弹簧),若不生效,看一下width()长度是否设置了
Toggle切换按钮
Toggle:可以设置为多个按钮(Checkbox复选框、Button按钮、Switch开关) **** Button按钮比较特殊和其他不同,如下:
/*
* Checkbox :复选框
* Switch 开关
* Button: 按钮 ,需要在里面设置文本
* */
Checkbox :复选框:
Toggle({ type: ToggleType.Checkbox, isOn: false })// isOn: true:默认 false:非默认。
Switch 开关:
Toggle({ type: ToggleType.Switch, isOn: true }) // isOn: true:默认 false:非默认。
Button: 按钮 ,需要在里面设置文本
Toggle({type: ToggleType.Button,isOn: true}) {Text("按钮")}
CheckBox 复/多选框
Checkbox({name:'名称',group:'分组'})
.select(true) // 默认
.selcectColor("颜色") // 复选框颜色
.onChange((val)=>{ "业务体" }) // 改变事件
Select选中框
Select选项是个数组的方式[]
icon: 可以为每个选项设置图片
@State opers:[] = [
{value:'一级',icon:"图片路径"},
{value:'二级'}
]
select(opers)
.value("请选择选项") // 设置提示
.selected(1) // 根据下标默认选择
.selectedOptionFont({size:20}) // 选中的字体大小
.optionFont({size:20}) // 选项大小
.onselect((index)=>{ // 选择触发事件 index为数组下标
})
Slider进度滑动组件
Slider({
value: 'number默认值',
min: 0, // 最小
max: 60, // 最大
style: SliderStyle.OutSet, // OutSet:滑块在滑轨上。 InSet:滑块在滑轨内。
direction: Axis.Vertical // 竖着,默认水平
})
.showTips(true) // true:滑动显示%
.trackColor('#bbb') // 未滑动颜色
.selectedColor('#bbb') // 已经滑动颜色
.blockColor('#ff2778f1') // 滑块颜色
.showSteps(false) // 是否显示刻度值
.onChange((value: number, mode: SliderChangeMode) => {
this.intervalMinute = value
})
Progress进度条
默认横着:可以通过宽度设置宽度, 当高度大于宽度,则会变为竖的进度条
Progress({value:当前进度,total:100(一般是100好计算) ,type:ProgressType.__值__})
ProgressType:
Linear : 线性
Ring:环形
ScaleRing:刻度进度条
Eclipse:圆形
Capsule: 胶囊
例:
Progress({value:num , total:100,type:ProgressType.___值___})
.style({strokeWidth: 30 }) // 当为环形时设置厚度
.style({scaleCount: 60}) // 当为刻度进度条 可以设置刻度数量
Router路径跳转
Router的使用需要导入包: import router from '@ohos.router' --当使用时,会自己导入
使用方法:
1.在需要路由跳转的路径需要在src/main/resources/base/profile/main_pages.json的位置添加路径信息
若启动模拟器:则查看: src/main/ets/entryability/EntryAbility.ts 下的启动首页路径需要配置为首页的
2.开始使用 router.pushUrl({url:"跳转到那个文件的路径",params:'参数'}) 或者 router.replaceUrl({url:"跳转到那个文件的路径",params:'参数'})
3.当退回使用 router.pushUrl({url:"跳转到那个文件的路径",params:'参数'})
或者
router.back()
或者
router.back({
url: 'pages/Index',
params: { msg: "这是上个页面的返回信息" }
})
4. 当路由完成可以在声明周期结束时清除路由: router.clear()
**扩展: pushUrl() 与 replaceUrl()的区别:
pushUrl: 使用跳转可以返回上一级页面。
replaceUrl: 使用跳转不能跳转上一级页面,比如首页展示
具体看情况而定
5.接收参数
Arrs:类型 = router.getParams()["msg"] // 接收看传递的是什么类型
router知识点:
1.router的2中实例模式:单例(Single)和多例(Standard)===>默认:多例(Standard)
2.router.pushUrl()区别:
多例(Standard):默认为多例,跳转时则会往栈中添加一条路由,栈中只能存32个路由,因此在合适的位置需要使用clear()清除路由
单例(Single):若栈中没有保存当前路由,则会往栈中添加一条,当存在时则是直接在栈中拿。这种页面会存在一定的页面缓存效果。若是局部刷新的话,则在需要跳转之前先操作。
3.router.pushUrl() 与 router.replaceUrl()的区别:
相同点:都可以使用参数进行传参。
router.pushUrl():当使用跳转时会往栈中添加一条路由,可以使用router.back() 进行返回,可以返回上一级。
router.replaceUrl():进行跳转时,则会将当前的路由进行替换,当返回时直接退出应用系统。
扩展setInterval 与setTimeOut的区别
格式:
let id = setInterval(()=>{},时间) // 每搁多长时间,执行一次
let id =setTimeOut(()=>{},时间) // 延迟多长时间开始执行,执行完就结束了
当使用完成,需要关闭需要调用各自的.clearInterval(id) 或者 clearTimeOut(id)函数
setInterval(): 每50ms执行一次:
let dingshi = setInterval(()=>{
if (this.sum ==100) {
this.is = true
this.sum = 0
clearInterval(dingshi) // 清除,否则页面不变化,但是内部还在执行
} else {
this.sum++
}
},50)
setTimeout(): 延时50ms执行:
let dingshi =setTimeout(()=>{
// 业务体
clearTimeOut(dingshi)
},50)
四、盒子模型和布局
Padding内边距
Border边框
用法:
Text() // 可以为其他组件
// 上使用线:Solid 实线、Dashed 虚线(短线)、 Dotted: 虚线(点)
.border({width:1,color:Color.Green,style:BorderStyle.Solid}) // 边框宽度,粗细颜色,实线
borderRadius圆角
borderRadius: 生成的样式,为矩形把角磨圆的形状为圆角
针对四个角设置
// 格式一
.borderRadius(10) // 将圆角设置为10, 当为正方形时,设置一半的长度图形为圆形
// 格式二
.borderRadius({ // 单独设置每一个角
topLeft: 40,
topRight: 10,
bottomLeft:10,
bottomRight:40
})
.clip(true) // 裁剪 当有图片时,可能导致样式不显示,此时可以使用
Margin外边距
Column列
格式:Column(){ }// 在上级为build() 时 每个自定义组件中,统计的只能存在一个 ,因为只能存在一个节点
组件可以设置每个子组件的间距:
Column({space:30}){} // 各间距30vp
Row行
格式:Row(){} // 在上级为build() 时 每个自定义组件中,统计的只能存在一个 ,因为只能存在一个节点
主轴交叉轴
Column:
列的主心轴为竖着的
设置使用.justifyContent(FlexAlign.____) //Start 主轴起始对齐 Center中间对齐 End:末端对齐 SpaceBetween 之间均分 SpaceAround两边一半均分 SpaceEvenly 包含空格
列的交叉轴为横着的
设置使用.alignItems(HorizontalAlign.____) //Start 主轴起始对齐 Center中间对齐 End:末端对齐
Row:
行的主心轴为横着的
设置使用.justifyContent(FlexAlign.____) //Start 主轴起始对齐 Center中间对齐 End:末端对齐 SpaceBetween 之间均分 SpaceAround两边一半均分 SpaceEvenly 包含空格
行的交叉轴为竖着的
设置使用.alignItems(VerticalAlign.____) //Start 主轴起始对齐 Center中间对齐 End:末端对齐
共用组件属性:
某个条件来设置方向(从左至右,还是从右至左)
.direction(true ? Direction.Rtl : Direction.Ltr) // Rtl :从右至左,否则取反
Blank自适应拉伸,缩放,延伸 弹簧
Blank(): 将两个组件弹开,可以使用在2个按钮之间,如设置里面的数据信息也是可以的
layoutWeight自适应缩放 内容的占比
layoutWeight(number) :根据设置的占比自己调整
例:
@Component
struct AlterInDome {
build() {
Row() {
Column() {
}
.width(50)
.height(30)
.backgroundColor(Color.Gray)
.border({ width: 1 })
// 设置内容的占比 ,也可以设置宽度百分比进行
.layoutWeight(1)
Column() {
}
.width(50)
.height(30)
.backgroundColor(Color.Gray)
.border({ width: 1 })
.layoutWeight(1)
Column() {
}
.width(50)
.height(30)
.backgroundColor(Color.Gray)
.border({ width: 1 })
.layoutWeight(2)
}
.width("80%")
.backgroundColor(Color.Red)
}
}
Scroll滚动条
格式:
@Compocnent
struct 自定义组件名称{
build(){
Scroll(){ // 滚动条组件
Column(){} //或者其他组件
}
.在这添加属性
}
}
属性:
.scrollable(ScrollDirection.___) // Vertical:垂直方向移动 、 Horizontal:水平方向
.scrollBar(BarState.On) // 显示滚动条 on:显示 auto:当滚动出现, off:不显示滚动条
.scrollBarColor("") //滚动条颜色
.edgeEffect(EdgeEffect.Spring) // Spring:到边缘回弹 Fade:边缘滑动效果为“渐隐”效果
五、动态元素UI构建
页面声明周期
onPageSHow(){}:当点击这个页面时,开始这个路由时执行, 在vue中其实就是钩子函数 等于create,在这叫声明周期
onPageHide(){}: 当这个页面被置动至后台。使用的声明周期
onBackPress(){}: 当页面点击退出调用此声明周期
组件声明周期
当单击页面的是由优先加载组件,因为页面就是组件渲染出来的。
aboutToAppear(){}: 组件开始加载时调用,在执行build() 函数之前执行
aboutToDisappear(){}: 关闭组件时调用
页面和组件声明周期顺序
1.aboutToAppear()-->组件声明周期
2.build()
3.onPageSHow() -->页面声明周期,开启页面展示/渲染
4.方式一: 当页面置于后台,调用onPageHisde() -->开启页面隐藏
方式二: 当页面退出时执行onPagePress()-->开启页面退出 后执行 onPageHide()-->开启页面隐藏
5.aboutToDisappear() -->关闭组件
@Builder局部自定义构建函数:
调用需要使用this
格式:
@builder 组件名(str:string,....){} // 可以传多个参数
调用:
this.组件名("",....)
@Builder全局自定义构建函数:
调用直接调用,定义则需要使用Function
格式:
@builder function 组件名(str:string,....){} // 可以使用参数
调用:
组件名(str:string,....)
@Builder参数传递
自定义函数支持两种方式传递:
按值传递: 如组件名(str:string,....) 也就是栈中的数据
按引用传递:定义参数需要使用($$:类型)
定义组件格式:
@Builder
getCellContent($$: CellParams){}
调用不变
getCellContent({"对象属性":"对象属性对应的值"})
@BuilderParam占位符、插槽
可以理解为自定义组件,构建自定义UI页面,此功能只要是定义一个插槽,可以后填充自定义组件。
属于在组件内的某一个位置使用插槽当不使用的时候,则页面不会渲染。
语法:
@BuilderParam name:()=>void // ()=>void 无返回值的箭头函数
格式:
1.定义一个UI渲染入口@Entry
2.定义一个自定义构建函数@Builder和自定义组件@component
3.定义一个插槽@BuilderParam
第一步:
@Entry
@Component
struct PageName{
@Builder
getContentParam(str:string){
Column(){
Text(str)
.backgroundColor(Color.Pink)
}
}
build(){
Column(){
// 调用子组件
// 方式一 : 尾随闭包传递 仅适用于定义了一个@BuilderParam
Card(){
this.getContentParam("这里是卡槽传值1")
this.getContentParam("这里是卡槽传值2")
this.getContentParam("一个插槽可以调用多个")
}
// 方式二: 多个@BuilderParam 插槽传值方式
Card({Content:()=>{
this.getContentParam("多个BuilderParam需要这么传值") // 不能一次性调用好几个一样的
}})
}.width("100%")
.height("100%")
}
}
第二步:
@Component
struct Card{
// 定义一个变量传值
label:string= '自定义组件值'
// 插槽
@BuilderParam Content:()=>void // Content 作为插槽函数
build(){
Column(){
Text("卡片组件这里不是插槽")
Divider()
if(this.Content){ // 可以不用加判断,为了防止报错,加入判断
this.Content()
}
}
}
}
@Styles组件样式重用的封装
@Styles:装饰器不支持参数传递
当定义全局的时候需要使用function ,使用时直接点这个组件就可以
格式:
全局:
@styles funcation fun(){
.width("100%")
.height("100%")
}
局部
@Component // 需要注册为组件
@styles fun(){
.width("100%")
.height("100%")
}
调用方式:
Text()
.fun()
@Extend 扩展组件样式
仅支持在本文件内使用
格式: UIComponentName 代表:TEXT,Button,...等组件
@Extend(UIComponentName) function functionName(size:number,width:string|number){ // 可以传参数
.fontSize(size)
.width(width??"100%") // ??:当不传值则默认
.fun() // 可以调用使用@styles装饰器封装的样式
}
调用:
Text()
.functionName(20) // 有参数需要传值
stateStyles多态样式
stateStyles 是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以
下四种状态:
focused:获焦态。
normal:正常态。
pressed:按压态。
disabled:不可用态。
**normal 和 disabled 都存在时 disabled不会好用一般增加变量通过 normal 实现效果
例:
@Entry
@Component
struct StateStylesSample {
build() {
Column() {
Button('Button1')
.stateStyles({
focused: {
.backgroundColor(Color.Pink)
},
pressed: {
.backgroundColor(Color.Black)
},
normal: {
.backgroundColor(Color.Red)
}
})
.margin(20)
Button('Button2')
.stateStyles({
focused: {
.backgroundColor(Color.Pink)
},
pressed: {
.backgroundColor(Color.Black)
},
normal: {
.backgroundColor(Color.Red)
}
})
}.margin('30%')
}
}
Flax弹性布局
语法使用和ROW和Column一致,里面增加包含了方向的排列方式
/**
* 当超出100%后默认压缩,不会自己换行
* Wrap:换行
* NoWrap:不换行
* WrapReverse: 换行反转
*/
Flex({wrap: FlexWrap.WrapReverse }) { } // 默认Row
Flex({ direction: FlexDirection.Column, wrap: FlexWrap.WrapReverse }) { }
也存在:主轴justifyContent,和交叉轴ItemAlign的对齐方式
Flex({ direction: FlexDirection.Column, wrap: FlexWrap.WrapReverse ,justifyContent:FlexAlign.____,alignItems:ItemAlign.___ }) { }
position()绝对定位
作用:控制组件位置,可以实现层叠效果
特点:
1. 参照 父组件左上角 进行偏移
2. 绝对定位后的组件 不再占用自身原有位置
position({x:num,y:num})
offset()偏移
属性:offset()
参数: {x: 水平偏移量, y: 垂直偏移量}
格式:
.offset({
x: 100,
y: -30
})
相对定位特点:
1. 相对自身左上角进行偏移
2. 相对定位后的组件仍然占用自身原有位置
Z序控制 : zIndex(数字)
定位后的组件,默认后定义的组件在最上面显示,可以通过 zIndex 属性调整显示层
级
属性: zIndex(数字)
特点:取值为整数数字,取值越大,显示层级越高
例:
// Z 轴显示顺序,取值越大,显示层级越高
.zIndex(1)
ForEache用法、数组
forEach(arr数组,()=>{
//业务
})
扩展特殊用法:
let mouth: string[] = Array.from(Array(12), (v, i) => { // 定义一个长度的空数组
return (i + 1).toString() // 根据下标进行返回 若长度不足2位,则使用0填充
})
// 当只有数字受限制语法时,可以进行填充
let mouth: string[] = new Array(5).fill('') // 填充空字符串
LazyForEach(懒加载)用法、数组
思路: 1.首先创建对象并实现IDataSource 接口
2.创建变量,变为LazyForEach所接受的类型
3.使用LazyForEach组件
举例:
1.首先创建对象并实现IDataSource 接口
// 将数据修改为懒加载
export class MyVideoDataRescuer implements IDataSource {
private dataArray: VideoItem[]
constructor(dataArray: VideoItem[]) {
this.dataArray = dataArray
}
totalCount(): number {
return this.dataArray.length
}
getData(index: number): VideoItem {
return this.dataArray[index]
}
// 后面为修改变更使用.参考官网
registerDataChangeListener(listener: DataChangeListener): void {
}
unregisterDataChangeListener(listener: DataChangeListener): void {
}
}
2.创建变量,变为LazyForEach所接受的类型
@State tableList: VideoItem[] = allData
// 创建的对象
bannerList = new MyVideoDataRescuer(this.tableList)
3.使用LazyForEach组件
LazyForEach(this.bannerList, (item: VideoItem, index: number) => {
// VideoCom({ item: item }) 组件或者渲染UI
})
Stack()堆叠布局
层叠布局具有较强的页面层叠、位置定位能力,其使用场景有广告、卡片层叠效果等。
并且可以设置对齐方式
例:
Column(){
Stack({alignContent: Alignment.____ }) { // 设置对齐方式
// 可包含多个组件,并可以对某一个组件设置 zIndex() 控制
Column()
Button('button')
}
Grid()网格布局
需要与子组件GridItem(){}连用,GridItem里面只能包含一个组件间,若想有多个则进行Row()或者Column()包装起来,如:计算机的排列
属性:
1. rowsTemplate和columnsTemplate 是设置排列方式的,作用于Grid(){}组件上
属性值是一个由多个空格和 数字 + fr 间隔拼接的字符串,fr 的个数即网格布局的行或列数,fr 前面的数值大小,用于计
算该行或列在网格布局宽度上的占比,最终决定该行或列的宽度。
***特殊:当设置的时候仅设置一个,并且页面展示不够的时候,可以实现滚动效果,组件自带的功能
格式:
Grid() {
...
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 2fr 1fr')
2..columnsGap 和rowsGap 行列间距,等同于设置 column({speac:30})类似,各组件之间的间距为多少
格式:
Grid(){}
.columnsGap(10)
.rowsGap(15)
3.子组件网格合并:
GridItem() {
Text(key)
...
}
.rowStart(5) // 从第几行开始
.rowEnd(6) // 至第几行结束
或者
.ColumnStart(5) // 从第几行开始
.ColumnEnd(6) // 至第几行结束
六、UI的渲染控制
Math对象
Math 是一个内置对象,它拥有一些数学常数属性和数学函数方法, Math 用于
Number 类型数据的处理
Math.random() // 获取随机数 [0,1) 可以取到0但是取不到1
例:
// 0-10 之间的随机 整数
console.log('Math对象', Math.floor(Math.random() * 11))
Math.ceil() // 向上取整 也称天花板函数
Math.floor() // 向下取整 也称地板函数
// 4-12 之间的随机 整数
// Math.floor(Math.random() * (差值 + 1) + 最小值)
console.log('Math对象', Math.floor(Math.random() * 9 + 4))
If(){}else{}判断
一般用在子组件判断显示和状态判断,这个比较熟悉。
ForEach()循环判断
格式:
ForEach(
arr: Array, // 数组
itemGenerator: (item: any, index: number) => void, // 组件生成函数
keyGenerator?: (item: any, index: number) => {return string} // 键值生成函数 ,显示规则生成函数,需要reture string
)
七、简单容器组件使用
7.1 通用属性
linearGradient()颜色渐变效果 :线性渐变==线性
####线性渐变
格式: .lineearGradient({
angle?: 线性渐变的起始角度,
direction?: 线性渐变的方向,
colors: [[颜色1, 颜色1所处位置], [颜色2, 颜色2所处位置],......],
repeating?: 是否重复着色
})
例:
Text('渐变颜色')
.width("100%")
.height(30)
.linearGradient({ // 渐变颜色效果
angle:49, //不常用 :线性渐变的起始角度。0点方向顺时针旋转为正向角度,默认值:180 当使用这个direction属性不生效
direction: GradientDirection.___, // 方向 Right:右侧: left:左侧及其他常用方位
colors: [["颜色", number值颜色所处位置], ["另一个颜色", 颜色所处位置],......] // 从哪个方向渐变为另一个颜色
})
radialGradient()颜色渐变效果 :径向渐变== 圆形
格式: radialGradient(
center: 径向渐变的中心点坐标,
radius: 径向渐变的半径,
colors: [[颜色1, 颜色1所处位置], [颜色2, 颜色2所处位置],......],
repeating?: 是否重复着色
)
例:
Text("径向圆形")
.width(100)
.height(100)
.radialGradient({
center:[50,50], // 径向渐变的中心点坐标 当前长度的一半(行,列),
radius: 50 // 半径
colors: [["#f00", 0], ["#ff0", 0.7],......
})
.borderRadius(50) // 文本圆角
shadow()阴影效果
格式: shadow(
{
radius: 模糊半径,
color ?: 阴影颜色
offset?: x轴偏移
offsetY?: Y轴偏移
}
)
例:
Text("阴影")
.width(100)
.height(100)
.margin(20)
.show({ // 阴影组件及属性
radius: 80, // 圆角
color: "#ffd90d0d", // 颜色
offsetX: 100, // 左偏移
offsetY: 50 // 下偏移
})
animation动画
可以结合伪类stateStyles 进行结合使用
Text("动画")
.fontSize(40)
.backgroundColor(Color.Pink)
.width("100%")
.height("100")
.stateStyles({
pressed:{.height(150)}
})
.animation({
duration: 3*1000 // 多久执行完
curve: curves.springMotin(), // 缓和的速度曲线,默认:Curve.Linear
delay: 1*1000, //延时多长时间执行
iterations: -1, // 无线动画次数 默认1次,当为-1为无限次,0无动画效果
onFinish:()=>{
// 动画完成执行的业务
}
})
图形变换
用于对组件进行平移translate、旋转rotate、缩放scale、矩阵变换等操作。
结合着伪类stateStyles使用,主要是变化效果
translate() 平移
格式:
.translate({x?: X轴移动距离, y?: Y轴移动距离, z?: Z轴移动距离})
例:
Text("移动动画")
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.stateStyles({
normal:{ // 正常
.translate({x:0})
},
pressed:{ // 按压
.translate({ y: 100, x: 0, z: 300 })
}
})
.animation({ // 动画
duration:3*100,
curve: curves.springMotion(), // 缓和的速度曲线
})
scale() 缩放
格式: .scale( {x?: X轴缩放比例, y?: Y轴缩放比例, z?: Z轴缩放比例, centerX?: Y轴中心
点坐标, centerY? Y轴中心点坐标})
例:
Image($r("app.media.icon"))
.width(200)
.animation({
curve: curves.springMotion()
})
.stateStyles({
normal: {
.scale({ x: 1, y: 1 })
},
pressed: {
.scale({ x: 0.5, y: 0.5 }) // 原比例缩放
}
})
rotate() 旋转
格式: .rotate({angle: 旋转角度, centerX?: Y轴中心点坐标, centerY? Y轴中心点坐标})
Text("旋转文字")
.fontSize(40)
.width("100")
.height(100)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.stateStyles({
normal: {
.rotate({ angle: 0 }) // 旋转角度
},
pressed: {
.rotate({ angle: 90,x:5,y:5 }) // 旋转角度,默认顺时针
}
})
7.2 List列表
基本使用
List 组件主轴默认是垂直方向,即默认情况下不需要手动设置 List方 向,就可以构建
一个垂直滚动列表。 若设置水平方向如下:
格式:
// 当使用滚动条时: List({ scroller: this.scroller,initialIndex:0 }) { //初始化滚动
List(){}
.listDirection(Axis.Horizontal) // 水平方向 相当于设置主轴, 不设置默认垂直方向
.alignlistItem(ListItemAligin.Center) // 设置交叉轴
list组件中包含:ListItem 和 ListItemGroup 子组件,其中 使用ListItem 组件中只能存在一个组件
***List的子组件必须是ListItemGroup或ListItem,ListItem和ListItemGroup必须配合List来使用。
格式:
默认垂直:
List(){
ListItem() {
Text("") // 只能有一个组件,若需要存在多个,可以使用colum()或者Row()其他组件进行套起来
}
}
水平:
List(){}
.listDirection(Axis.Horizontal) // 水平方向 相当于设置主轴, 不设置默认垂直方向
.alignlistItem(ListItemAligin.Center) // 设置交叉轴
divider分割线属性
分割线: 作用域List(){}组件上
例:
List(){}
.divider({
strokwidth:1 ,// 分割线宽度
startMargin:60, // 开始位置
endMargin:10, // 结束距离
color:Color.Pick // 颜色
})
Badge列表标记
Badge列表添加标记: 作用于List显示的某个组件之上。
例:
List() {
ForEach(this.contact, (item: Contact, index: number) => {
ListItem() {
Row() {
// 图片
if (this.contact.length - 1 == index) {
Badge({ //** 判断为那个列表添加标记
count: 1, // 标记显示数量,只能为number类型,当超过100则显示99+
position: BadgePosition.RightTop, // 显示位置
style: { badgeSize: 20, badgeColor: Color.Red } // 标记的大小和颜色
}) {
Image(item.icon).width(50)
}
.margin(10)
} else {
Image(item.icon).width(50).margin(10)
}
// 文本
Text(item.name)
}.width("100%")
}
})
}
scrollBar滚动条
scrollBar:作用于List()组件之上
格式:
List(){}
.scrollBar(Barstate.Auto) // 是否显示滚动条 on 开 off关 auto 自适应滚动显示
ListItemGroup分组列表
如:手机联系人页面,实现分组和快速定位的功能
格式:
数据格式: {title: 'A', data:[]}
build() {
List() {
ListItemGroup({ header: this.itemHead('A') }) { // 需要自己分组后才会展示正常
// 循环渲染分组A的ListItem 对应data[] 数据
...
}
...
ListItemGroup({ header: this.itemHead('B') }) {
// 循环渲染分组B的ListItem
...
}
}
}
Scroller滚动位置控制
Scroller的使用需要先创建这个对象, 作用于List()组件。
listScroller: Scroller = new Scroller()
在使用的时候调用 this.listScroller.scrollToIndex(0) // 数组的下标,用于回到那个位置 0:代表置顶、头部
使用的是否可能会使用到Stack()堆叠布局,可以实现在List列表层级上显示
格式:
提供数据格式: {title: 'A', data:[]}
1.创建Scroller滚动条对象
listScroller:Scroller =new Scroller()
2.渲染UI
build(){
Stack({alignContent: Alignment.BottomEnd}){ // 堆叠布局,设置对齐方式,这里右下
List({scroller:this.listScroller,listScroller?: 0}){ // 通过将listScroller用于初始化List组件的scroller参数,完成listScroller与列表的绑定。在需要跳转的位置指定scrollToIndex的参数为0,表示返回列表顶部。
forEach(ArrArrs,(itemArr)=>{
ListItemGroup({heard: 这是一个自定义函数,见:itemHeader例子}){
forEach(itemArr.arr,(item)=>{
.......
})
}
})
}.width("100%")
.onScrollIndex((start:number,end:number)=>{
// 可以获取数组的下标, 可以获取控制AlphabetIndexer的响应控制,见:AlphabetIndexer响应滚动控制内容
})
Button("顶部")
.onClick(()=>{
3.变更控制
this.listScroller.scrollToIndex(0) // 回到顶部
})
}
}
@Builder function itemHeader(msg: string) {
Text(msg)
.fontSize(20)
.backgroundColor(Color.Green)
.width("100%")
.padding(5)
}
AlphabetIndexer响应滚动控制
联系人右侧的字母
需要结合Stack堆叠布局进行使用
格式:
listScroller:Scroller = new Scroller()
build(){
Stack(){
List({scroller:this.listScroller,listScroller?: 0}){} // 列表数据 **必须设置属性用于响应
AlphabetIndexer({arrayValue: arr[]字符串数组数据,selected: 默认值,数组下标}){ //响应滚动控制组件 ,selected 可以根据onScrollIndex属性设置动态默认值
.itemSize(30) // 数组各之间的间距
.font({size:20}) // 字体大小
.selected(动态获取下标数据)// 当设置选中,则组件中使用的 selected不会生效,一般使用组件中的,动态获取就可以
.selectedColor(Color.____) // 选中的颜色
.usingPopup(true) // 电锯选中后,当前字体会有一个弹出框,相当于放大
.onSelect((index:number)=>{
// 选中后显示的数组下标,可以控制页面列表信息显示对应信息
this.listScroller.scrollToIndex(index)
})
}
}
}
swipeAction列表事件,左右滑动
swipeAction属性,作用于ListItem()组件接收的是个自定义函数,用于显示左右滑动显示的功能,比如:删除
格式:
ListItem(){}
.swipeAction({end: this.itemEnd(下标:number)}) // 自定义函数格式
@Builder itemEnd(index:number){
Button({type:ButtonType.Circle}){
Image($r("app.media.delete"))
.width(25)
.height(25)
.fillColor(Color.Red)
}
.onClick(()=>{
// 相关业务处理
})
}
7.3 滚动Scroll、Scorrer
Scroll组件
Scroll 默认竖着滚动,当数据页面超过设置的高则才会生效
格式: Scroll(){}
.scrollable(ScrollDirection.____) // Vertical:默认竖着 Horizontal:水平滚动
.scrollbar(BarState.____) // On off auto 按需显示, 滚动条关闭显示不会影响滚动
.scrollBarColor(Color.Green) // 设置滚动条颜色
.scrollBarWidth(20) // 设置滚动条宽度
.onScroll((x,y)=>{}) // 获取实时滚动条位置
.onScrollEdge(()=>{}) // 滚动结束触发
.onScrollStop(()=>{}) // 滚动暂停触发
.onScrollStart(()=>{}) // 滚动开始触发
Scorrer控制器
需要重新创建对象:
scroller: Scroller = new Scroller()
结合滚动组件的用法格式:
Scroll({this.scroller}){}
滚动控制属性:
scroller: Scroller = new Scroller()
this.scroller.scrollTo({xOffset:0,yOffset:700}) // 滚动到某个位置
this.scroller.scrollTo({xOffset:0,yOffset:0}) // 顶部
this.scroll.scrollEdge(Edge.Bottom) //跳转到边界位置 上中下
this.scroll.scrollPage({next: boolean}) // true:跳转下一页 false:跳转上一页
八、Swiper轮播组件
组件格式: Swiper(){} // 使用和滚动控制类似
SwiperController // 导航控制器
步骤:
1.创建导航控制器:swiperController:SwiperController = new SwiperController()
属性:
.showNext() // 切换下一个图片
.showPrevious() // 切换上一个图片
2.创建组件:
Swiper(this.swiperController) { // 用于后面的其他功能
forEach(Array,(item:object,index:number)=>{
// UI
})
} // swiper的属性
.autoPlay(true) // 是否轮播 true:轮播 false: 不轮播
.loop(true) // 播完时候回来,等于循环
.interval(3*1000) // 多久切换一次
.indicator(true) // 是否显示导航条,默认显示
.index(1) // 默认显示哪一个数组下标
.indicatorStyle({ // 导航条属性
bottom:10,
color: ,
selectColor: // 选中的颜色
})
.onChange((index: number) => { // 当进行轮播时,获取当前的Index
// this.curIndex = index
})
九、Tabs组件
tabs组件中需要使用 TabContent()和tabBar() 子组件。
格式:
tabs({barPostition:BarPosition.Start}){ //若不设置则默认在上面, Start:上面, End:下面。
// 若设置左侧或者右侧需要增加一个 .vertical(true) 结果: Start + true= 左侧 End + true = 右侧
TextContent(){
Text("文章内容")
}
.tabBar("首页") // 可以是文本也可以是自定义函数或者组件
}
.vertical(true) //设置首页在左侧或者右侧使用 结果: Start + true= 左侧 End + true = 右侧
.barWidth(100) // 标题的宽度
.barHeight(100) //标题的高度
.barMode(BarMode.Scrollable) //默认值:Fixed。 若导航太多时,可以设置为滚动,不设置显示不开,会显示成“.”
十、Navigation分栏、标题栏、工具栏,导航栏组件
Navigation():主页面组件,在内容区可以使用NavRouter()实现导航栏功能,其中子组件导航栏内容需要有NavDestination()进行渲染。
等级:Navigation(主组件) -->NavRouter(主组件内容)-->NavDestination(子组件内容)
格式:
Navigation(){
Text("主组件")
NavRouter() {
Text("导航栏")
NavDestination(){
Cloum(){Text("点击导航显示的内容")}
}
.title("点击的小标题")
}
}
.title("主标题")
.mode(NavigationMode.Auto) // 不设置默认Stack(覆盖当前的页面), Split:将当前页面进行分栏,主题一半,内容一半
.titleMode(NavigationTitleMode.___) // 看主页面的间距发生变化了
.menus( // 菜单栏,缩略部分不显示图片 显示在上部
[{value: '菜单栏名称',icon: '字符串格式的图片,可以放在page下或者远程',action:()=>{
// 当点击处理的事件
}}])
.toolBar(
{
item:[{value:'工具栏名称',icon:'图片',action:()=>{
//当点击处理的事件
}}]
})
十一、TextPicker文本选择器
格式:
TextPicker({
rang:arr数组,
selected:默认值,写数组下标
value: 默认值,写内容非下标
})
.onchange((val,index)=>{})
十二、TextPickerDialog弹框
TextPickerDialog.show({
range:[“-1”, “0”, “1”, “2”, “3”],
selected:1,
onAccept:(val:TextPickerResult)=>{},
onChange:(res:TextPickerResult)=>{res.value+res.index},
onCancel:()=>{}
})
十三、TimePicker选择器
TimePicker({
selected:new Date(), // 默认
})
.useMilitaryTime(true) // 按照24小时显示
.onchang((val:TimePickerResult)=>{
// 接收的参数是24小时,和useMilitaryTime无关
promptAction.showToast({ message: '' + val.hour + ":" + val.minute })
})
十四、TimePickerDialog弹框
TimePickerDialog.show({
useMilitaryTime: true, // 是否开启24小时
selected: new Date(), // 默认选择
onAccept: (value: TimePickerResult) => {
promptAction.showToast({ message: "确认" + value.minute })
},
onCancel: () => {
promptAction.showToast({ message: "确认" })
},
onChange: (value: TimePickerResult) => {
promptAction.showToast({ message: "确认" + value.minute })
}
})
十五、DatePicker选择器
DatePicker({
start:new Date(), // 开始时间,不设置为1969年
end:new Date(), // 结束时间 ,最大值2100
selected:new Date() // 默认时间
})
.lunar(true) // 是否使用农历
.onchang((value:DatePickResult)=>{
// 打印还是非农历进行输出的
promptAction.showToast({ message: value.year + "-" + (value.month + 1) + "-" + value.day })
})
十六、DatePickerDialog弹框
DatePickerDialog.show({
start: new Date("1997-10-06"), // 设置开始时间
end: new Date(), // 结束时间
selected: new Date(), //默认时间
lunar: true, // 是否开启使用农历日历
onChange: (val: DatePickerResult) => {
// 发生变更调用
promptAction.showToast({ message: "改变" + val.day })
},
onAccept: (res: DatePickerResult) => { // 确认调用
promptAction.showToast({ message: "改变" + res.day })
},
onCancel: () => { // 任意点击关闭弹出框调用
} // 返回
})
十七、自定义选择器 和 CustomDialog自定义弹框
自定义选择器 还是使用TextPicker实现
自定义弹框:需要创建CustomDialog并自定义构建组件或者函数来完成弹出框内容设计。调用内部的open() 或者close() 进行开启和关闭弹出框
CustomDialog自定义弹框:操作步骤:
1.创建自定义弹出框对象,并在该对象内传递参数信息,实现弹出框UI的页面:
dialog: CustomDialogController = new CustomDialogController(
{
// 自定义组件 使用@CustomDialog装饰器 和 controller:CustomDialogController
builder: 'this.组件名称()', //自定义组件或者函数,并可以传入想要的值
autoCancel: false, // 是否任意点击取消弹出框
alignment: DialogAlignment.Center, // 样式
cancel: () => {
this.commonDigMessage("点击任意取消")
},
}
)
2.创建自定义的组件, ***需要将@Component 替换为 @CustomDialog 并定义一个CustomDialogController属性,才可生效
格式:
strurt 组件名称{
controller: CustomDialogController // 作用可能是关闭弹框使用的
build(){}
}
3. 在需要用此弹出框是,根据创建的对象进行调用: this.dialog.open()
4.在关闭时,则在弹出框内调用常见的对象: this.controller.close()
十八、AlertDialog警告弹框
AlertDialog 存在2种重要区分一点击确定框的功能对应的参数不同
扩展: promptAction.showToast({message:'弹出后,会自己消失,短暂停留'}) 需要导包
方式1: 仅有一个确定按钮AlertDialogParamWithConfirm
AlertDialog.show({
message: '你是否喝酒驾车',
title: '警告提示'
alignment: DialogAlignment.Top, // 弹框对齐位置
autoCancel: false, //任意点击自动取消
autoCancel: false, //任意点击自动取消
offset: { dx: 0, dy: 100 }, // 位置偏移
confirm:{
value: '确定或者取消', // 仅一个
action:()=>{
// 业务处理
}
},
cencel:()=>{
// 任意随意点击弹出框消失,执行的业务
}
})
方式2(建议): 有多个按钮AlertDialogParamWithButtons
AlertDialog.show({
title: '标题',
message: "第二种",
autoCancel: false, // 自动取消
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -100 },
primaryButton: { // 确认按钮
value: "取消",
action: () => {
promptAction.showToast({ message: "取消" })
}
},
secondaryButton: {
value: "确认",
action: () => {
promptAction.showToast({ message: '点击确定' })
}
},
cancel: () => {
promptAction.showToast({ message: '任意取消' })
}
})
十九、ActionSheet列表弹框
ActionSheet.show({
title: "列表弹出框",
message: "请选择通知信息",
alignment: DialogAlignment.Center, // 位置
autoCancel: true, // 是否任意关闭
cancel: () => {
promptAction.showToast({ message: "任意取消" })
},
confirm: {
value: "确定",
action: () => {
promptAction.showToast({ message: "确定功能" })
}
},
sheets: [
{ title: "苹果", action: () => {
promptAction.showToast({ message: "pingguo" })
} },
{ title: "小脚", action: () => {
promptAction.showToast({ message: "pingguo" })
} },
{ title: "apple", action: () => {
promptAction.showToast({ message: "pingguo" })
} }
]
})
二十、装饰器传值和监听watch
@State:
只作用于当前组件 使用时需要赋值
@Prop:
父传子,但是子变更不了父 不需要赋值,若赋值则会报错,因为接收父组件值
@Link:
父子互传,但是父值一遍,所有子组件也就变化 不需要赋值,若赋值则会报错,因为接收父组件值
**@Link只能修改被@state修饰的变量。
@privoid @cusumer :
后代传值 2个装饰器需要结合使用,并且需要定义的变量名和类型保持一致,否则渲染不出来
// 当时后代传值,不需要在父类种传递参数;当子类,和后代都是用使用,按时按照父子组件对子组件@link进行传值,后代还是使用@Consume,对于提供者需要使用@provide进行装饰
@Observed @ObjectLink :
深层/多层数据监听。其中@Observed作用于对象属性, @ObjectLink作用于封装的多层数据结构。
使用此注解需要在创建对象时需要new Class() ,否则不生效
//限制: ObjectLink只能在子组件中使用,并且只能传递第二层的数据 如:City不是第一层的User Observed:则就对City类上标记注解
@watch("定义的函数名"):
监听状态管理。// 当初次使用监听不会被调用 @watch("定义的函数") 结合@state使用 如:简单的计算总和
二十一、状态存储
LocalStorage:页面级UI状态存储(局部、全局)
局部:
1.创建对象
export const res = new LocalStorage({key:{name:"你的名字",id:1} as User}) // 若在其他页面使用需要使用使用 export导出
2.需要在@Entry装饰器添加参数 如:@Entry(res)
3.根据对应的想要获取的参数,使用@LocalStorageProp("key") 或者 @LocalStorageLink("key")进行接收值
如:
@LocalStorageProp("key")
user:User = {} as User // 接收的参数需要默认值
全局: 需要在EntryAbility.ts文件中进行参数传递
1.创建定义的对象:
export const res = new LocalStorage({key:{name:"你的名字全局",id:1}})
2.在onWindowStageCreate()函数中进行传参,找到首页路径位置进行开始传参
windowStage.loadContent('pages/PersistentStoragePage',res(此处定义存储变量名), (err, data) => {})
3.外部使用 LocalStorage.GetShared():
如:
// 获取全局
let res =LocalStorage.GetShared()
//在注解将变量填入
@Entry(res)
//使用注解获取对应的数据,记得赋默认值
@LocalStorageProp("key") 或者 @LocalStorageLink("key")
use:User = {} as User
AppStorage:应用全局的UI状态存储
格式:
1.创建AppStorage并赋值:
AppStorage.SetOrCreate<User>('user', { name: 'appStorage使用', id: 3 }) // key:value格式
AppStorage.Set<User>("user2",{name:'',id:1})
2.获取key的方法 存在多种方式
2.1:使用注解
@StorageProp("user") 或者 @StorageLink("user")
user:User = {name:'',id:0} as User
2.2:只能获取无法修改
const user: User = AppStorage.Get('user')
2.3: 获取后可以赋值
const link:SubscribedAbstractProperty<User> = AppStorage.Link('user')
link.get().id;
link.get().name;
link.set({name:'aaa',id:2})
const prop:SubscribedAbstractProperty<User> = AppStorage.Prop('user')
prop.get().id;
prop.get().name;
prop.set({name:'aa',id:4})
PersistentStorage:持久化存储UI状态
PersistenStorage():可以将状态到磁盘中,每次退出将会记录最终的数据。
底层使用的是AppStorage,用法和AppStorage一致
格式:
1.赋值的全局数据:
PersistentStorage.PersistProp("key","保存信息")
2.获取方式:
方式一:
@StorageLink("key") 或者 @StorageProp('key')
message:string = ''
方式二:
let key = AppStorage.Get('key')
使用这种可以结合赋值: AppStorage.SetOrCreate('key',47);
Environment:设备环境查询
应用程序运行的设备的环境参数,以此来作出不同的场景判断,比如多语言,暗黑模式等,需要用到Environment设备环境查询。
如查询系统语言:
Environment.EnvProp('languageCode', 'en'); // 这里面赋值的为初始值
@StorageProp("languageCode") // 一般只会取值,不会修改,赋值的话也是改变系统属性的
lan:string = ''
二十二、手势
使用手势的步骤
1.绑定手势方法 。
存在3钟: 手势方法: 常规:gesture 优先级:priorityGesture 并行:parallelGesture
2.设置手势类型。
(TapGesture点触、LongPressGesture长按、PanGesture拖动、PinchGesture捏合、RotationGesture旋转、SwipeGesture滑动 并可以对这些样式进行组合使用使用GestureGroup组件)
3.绑定对应手势方法 格式:.手势方法(类型,响应方法())
知识点:
一:
* 手势方法: 常规:gesture 优先级:priorityGesture 并行:parallelGesture
* gesture:当父子组件都有绑定,会优先识别子组件手势,各执行各自的,子级优先
* priorityGesture::当父子组件都有绑定 优先执行父组件,子组件内部的也是使用父组件的手势,父级优先
* parallelGesture:父子组件同事绑定单击和双击,则只显示单击
二:
GestureGroup组合手势的3个类型:
GestureGroup(GestureMode.______,()=>{//Sequence : 组合顺序识别 ;Parallel:并发识别; Exclusive:互斥只有一个识别,其余的不执行
// 设置手势类型。
//可以设置的手势:TapGesture点触、LongPressGesture长按、PanGesture拖动、PinchGesture捏合、RotationGesture旋转、SwipeGesture滑动 和GestureGroup组合手势。 其中GestureGroup组合手势可其他的有些区别。
//使用TapGesture点触的手势进行举例:
TapGesture((e: GestureEvent)=>{
// 触发执行的业务,部分需要结合着其他属性来共同实现。如:拖动需要结合、捏合、旋转
})
})
三:
常用属性:
e.repeat // 是否重复,主要用于longPressGesture手势触发
e.offsetX // 左右偏移位置
e.offsetY // 上下偏移位置
e.angle // 用于RoationGesture: 表示旋转角度
e.scale // 缩放手势,用于捏合手势PinchGesture ,单位vp
e.pinchCenterX // 用于捏合手势PinchGesture ,单位vp
e.pinchCenterY //用于捏合手势PinchGesture ,单位vp
e.speed //: 滑动手势速度
e.fingerList // 数组 用于长按和点触的场景
e.timestamp // 时间戳
e.target // 对象显示区域的宽高
e.source // 事件输入设备, unknowm 未知 Mouse: 鼠标 TouchaScreen: 触摸屏
e.pressure // 按压压力的大小
e.tiltX // 手写笔夹角
e.tiltY // 手写笔夹角
e.sourceTool // 输入事件源
Gesture点击手势
Text("手势")
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.gesture(// 绑定手势
// 设置手势类型
TapGesture({ count: 2,fingers: 2 }) // 默认点击一次 count:次数,repeat:是否重复执行 ,fingers:手指数量。含义:2个手指共点击2次
//响应方法
.onAction((e: GestureEvent) => {
// 处理对应的业务
// promptAction.showToast({ message: e.offsetX + '' })
})
)
LongPressGesture长按手势
Text("手势")
.width(300)
.height(40)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.gesture(
LongPressGesture({
duration: 3 * 1000, // duration:按压多长时间执行 3S
repeat: false, // repeat:是否重复执行事件内容 默认false
fingers: 1 // 默认一个手指长按 fingers几个手指按压
}) ,
.onAction((e: GestureEvent) => {
promptAction.showToast({ message: e.offsetX + '' })
console.log(e.offsetX + '')
})
)
PanGesture拖动手势
@Component
struct PanGestureDome {
// 当前位置移动多少
@State x: number = 0
@State y: number = 0
// 改变后的当前位置,每次第二层触发会存在问题,需要记录结束的距离
@State yx: number = 0
@State yy: number = 0
build() {
Column() {
Text("拖动")
.width("100")
.height("100")
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.translate({ x: this.x, y: this.y }) // 平移
// .offset({x:this.x,y:this.y}) // 使用这个有问题
.gesture(
PanGesture({ direction: PanDirection.Vertical }) // 设置拖动方向
.onActionStart((e: GestureEvent) => {
promptAction.showToast({ message: '开始移动X:' + e.offsetX + ",Y:" + e.offsetY })
})
.onActionUpdate((e: GestureEvent) => {
this.x = e.offsetX + this.yx
this.y = e.offsetY + this.yy
promptAction.showToast({ message: '开始移动X:' + e.offsetX + ",Y:" + e.offsetY })
})
.onActionEnd((e: GestureEvent) => {
this.yx = this.x
this.yy = this.y
promptAction.showToast({ message: '开始移动X:' + e.offsetX + ",Y:" + e.offsetY })
})
)
}
.width('100%')
.height('100%')
}
}
PinchGesture捏合手势
@Component
struct PinchGestureDome {
// 当前位置移动多少
@State x: number = 1
// 改变后的当前位置,每次第二层触发会存在问题,需要记录结束的距离
@State yx: number = 1
build() {
Column() {
Text("捏合")
.width("200")
.height(200)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.border({ width: 2, color: Color.Green })
.scale({ x: this.x, y: this.x })
.gesture(
PinchGesture()
.onActionStart((e: GestureEvent) => {
promptAction.showToast({ message: "开始捏合" })
})
.onActionUpdate((e: GestureEvent) => {
promptAction.showToast({ message: e.pinchCenterX + "::" + e.pinchCenterY })
this.x = e.scale * this.yx
})
.onActionEnd(() => {
this.yx = this.x
})
)
}
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
.width('100%')
.height('100%')
}
}
RotationGesture旋转手势
@Component
struct RotationGestureDome {
@State angle: number = 0
@State Yangle: number = 0
build() {
Column() {
Text("旋转")
.fontSize(30) // 度数
.width("100")
.height("100")
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.rotate({ angle: this.angle })
.gesture(
RotationGesture()
.onActionUpdate((e: GestureEvent) => {
this.angle = e.angle + this.Yangle
})
.onActionEnd(() => {
this.Yangle = this.angle
})
)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
SwipeGesture滑动手势
@Component
struct SwipeGestureDome {
build() {
Column() {
Text("滑动")
.fontSize(30) // 度数
.width("100")
.height("100")
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.gesture(
SwipeGesture({ direction: SwipeDirection.All }) //滑动方向
.onAction((e: GestureEvent) => {
})
)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
GestureGroup组合手势
@Component
struct GroupDome {
build() {
Column() {
Text("组合")
.fontSize(30)
.width("100")
.height("100")
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
.gesture(
// GestureGroup 组合手势 ,多个手势使用","分割
GestureGroup(GestureMode.Exclusive, //Sequence : 组合顺序识别 ;Parallel:并发识别; Exclusive:互斥只有一个识别,其余的不执行
LongPressGesture() // 长按
.onAction(() => {
promptAction.showToast({ message: "组合中的长按" })
})
,
PanGesture()
.onActionUpdate(() => {
promptAction.showToast({ message: "组合中的拖动" })
})
)
)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
组合手势案例:(缩放、旋转、拖动)
@Entry
@Component
struct OperatePage {
// 放大scale
@State scale1: number = 1
@State scaleCopy: number = 1
// 旋转rotate
@State rotate1: number = 0
@State rotateCopy: number = 0
// 拖动translate
@State x: number = 0
@State xCopy: number = 0
@State y: number = 0
@State yCopy: number = 0
build() {
Column() {
Image($r("app.media.icon"))
// Text("滑动")
// .fontSize(30)
.width("100")
// .backgroundColor(Color.Pink)
.height("100")
.scale({x:this.scale1})
.rotate({ angle: this.rotate1 })
.translate({x:this.x,y:this.y})
.gesture(
GestureGroup(GestureMode.Parallel,
PinchGesture() // 捏合
.onActionUpdate((e: GestureEvent) => {
this.scale1 = e.scale * this.scaleCopy
})
.onActionEnd(() => {
this.scaleCopy = this.scale1
})
,
RotationGesture() // 旋转
.onActionUpdate((e: GestureEvent) => {
this.rotate1 = e.angle + this.rotateCopy
})
.onActionEnd(() => {
this.rotateCopy = this.rotate1
})
,
LongPressGesture() // 长按
.onAction(() => {
})
,
PanGesture({ direction: PanDirection.All }) // 拖动
.onActionUpdate((e:GestureEvent) => {
this.x = this.xCopy + e.offsetX
this.y = this.yCopy + e.offsetY
})
.onActionEnd(()=>{
this.xCopy = this.x
this.yCopy = this.y
})
)
)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
二十三、绘制组件
绘制组件包含:Circle圆形、Ellipse椭圆、Line线性、PolyLine折线、Polygon多边形、Path路径绘制、Rect矩形、Shape绘制组件父组件。
其中Shape父组件可以将单一的组件进行结合起来,可以实现类似SVG的效果
Circle圆形
Stack() { // 此处使用的堆叠布局
Text("加载...").zIndex(10) // Z序控制层级,否则此处将会被覆盖
Circle()
.width(100)
.height(100)
.fill(Color.Red) // 默认黑色 填充颜色
.fillOpacity(1) // 透明度 0-1
.stroke(Color.Yellow) // 边框颜色 ,结合边框宽度使用 ,否则没有宽度显示不出来
.strokeWidth(10) // 边框粗细
.strokeDashArray([10, 10]) // 齿轮 ,数组里面添加下数值
}
Ellipse椭圆
Ellipse()
.width("100")
.height(80)
.fill("#fa2") // 填充颜色
.stroke(Color.Green)// 边框颜色
.strokeWidth(3)
.strokeDashArray([10])
Line线性
Line()
.width(200)
.height(50)
.backgroundColor(Color.Green)
.startPoint([0, 0]) // 开始画线
.endPoint([45, 45]) // 结束画线
.stroke(Color.Pink)// 边框颜色
.strokeWidth(10)
.strokeLineCap(LineCapStyle.Round) // Round: 和 .borderRadius(25) 一样
.strokeDashArray([5, 10])//设置边框间隙。
.strokeDashOffset(20) // 边框绘制起点的偏移量
PolyLine折线
Polyline()
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.points([[0, 0], [20, 0], [30, 80], [0, 40], [100, 100]]) // [x,y]坐标 可以任意线如圆形
.stroke(Color.Red) // 边框颜色
.strokeLineJoin(LineJoinStyle.Round) // 设置边框拐角绘制样式
.strokeLineCap(LineCapStyle.Round) // 设置边框端点绘制样式
Polygon多边形
Polygon()
.width(100)
.height(30)
.backgroundColor(Color.Yellow)
.fill(Color.Pink)
.points([[0, 0], [0, 10], [10, 10], [10, 0]]) // 绘制矩形内的正方形
.fillOpacity(0.5)
.stroke(Color.Black)
Path路径绘制
Path()
.commands() // 属性
说明:
/**
后面跟着的是坐标 数值是像素px,但每个的属性都不一致具体的参考官方文档.
* M : 在某个位置开始画
* 小写的字母是基于上一节点的位置进行移动。可以理解为:其中小写的字母代码相对路径,大写字母代表绝对路径
*/
含义及举例:
//L : 从那个位置开始画直线
//mands("M 0 0 L(l) 0 100 (L)l 100 100")
//垂直线V
// mands("M 100 100 H 300 H 300") // H 绝对位置 画水平线
// mands("M 00 00 h 300 h 300") // h 相对位置 画水平线
// 垂直线V
// mands('M 0 0 V 100 V 300 ')
// mands('M 0 0 v 100 v 300')
// 弯曲 C
// mands('M 0 0 C 200 50 0 300 150 400 C 20 200 10 300 40 300' ) // 每 6个一组
// mands('M 0 0 c 200 50 0 300 150 400 c 20 200 10 300 40 300' ) // 每 6个一组
// 平滑弯曲 S
// mands('M 0 0 S 100 200 0 300 S 200 100 300 300')
// mands('M 0 0 s 100 200 0 300 s 200 100 300 300')
// 曲线Q
// mands('M 0 0 Q 100 200 0 300 Q 200 100 300 300')
// mands('M 0 0 q 100 200 0 300 q 200 100 300 300')
// T
// mands('M 0 0 Q 100 200 0 300 Q 200 100 300 300')
// mands('M 0 0 q 100 200 0 300 q 200 100 300 300')
// A 椭圆弧
//mands('M 0 0 A 100 100 0 0 200 200 ')
// Z 将终点和起点加入闭合
//mands("M0 300 S100 0 240 300 Z")
Rect矩形
Rect() // 默认黑色
.width("100")
.height(100)
.fill(Color.Blue) // 填充
.fillOpacity(0.5)// 透明度
.stroke(Color.Red)
.strokeWidth(3)
// .radiusWidth(20)
// .radiusHeight(50)
.radius([[50, 50], [50, 50], [10, 10], [10, 10]]) // 对每个角设置圆角
.strokeDashArray([10, 3, 1]) //设置边框间隙。
Shape父组件
依验证码生成为例(此处可以拿来即用):
@Entry
@Component
struct TaskWork {
/**
* 1.定义数组 数组和字母
* 2.定义2个接收数组 验证数组 和 颜色数组
* 3.使用 Shape: 绘制组件 Rect: 矩形 Text 文本 Path:路径
* */
@State data: (string | number)[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
@State yanZheng: (string | number)[] = []
@State colors: string[] = []
@State Lines:string[] = []
height1: number = 100
width1: number = 200
randomNumber(num:number) {
return Math.floor(Math.random()*num) // 随机数+地板函数
}
randomLine() {
// "M 0 0 L 0 0 "
return "M "+ this.randomNumber(this.width1)*3+" "+this.randomNumber(this.height1)*3 + "L"+ this.randomNumber(this.width1)*3+" "+this.randomNumber(this.height1)*3
}
randomRotate(){
const res = this.randomNumber(90)
if (res>45) {
return -(res-45)
} else {
return res
}
}
randomColor(){
let color = ''
for (let index = 0; index < 3; index++) {
color = color+','+Math.floor(Math.random()*255)
}
return "rgb("+color.replace(',','')+")"
}
// 初始化数据,组件打开时执行
aboutToAppear() {
this.colors= []
this.yanZheng = []
this.Lines = []
for (let index = 0; index < 4; index++) {
this.yanZheng.push(this.data[this.randomNumber(this.data.length)])
}
for (let index = 0; index < 9; index++) {
this.colors.push(this.randomColor())
this.Lines.push(this.randomLine())
}
}
build() {
Column() {
Shape() {
Rect() // 矩形
.width(this.width1)
.height(this.height1)
Row({ space: 0 }) {
ForEach(this.yanZheng, (item: number | string, index: number) => {
Text(item.toString()) // 文本
.fontSize(40)
.rotate({angle:this.randomRotate()})
.fontColor(this.colors[index])
})
}
.width(this.width1)
.height(this.height1)
.justifyContent(FlexAlign.SpaceEvenly)
.alignItems(VerticalAlign.Center)
ForEach(this.Lines, (line:string, index: number) => {
Path() // 路径绘制
.commands(line)
.stroke(this.colors[index])
.strokeWidth(2)
})
}
.width(this.width1)
.height(this.height1)
.fill(Color.Pink)
.opacity(0.5)
.onClick(() => {
this.aboutToAppear()
})
}
.width('100%')
.margin({top:10})
}
}
二十四、Canvas画布组件
格式:
1.创建对象
settings: RenderingContextSettings = new RenderingContextSettings(true)
context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
2.创建组件并绑定对象
Canvas(this.context)
.onReady(()=>{ // 特有属性
3.执行业务方法 调用 this.context中的属性
})
this.context中的属性:
1.this.context.save() :保存: 不加就会导致图片绘制一动全动,根据情况加入
2.this.context.translate()平移
3.this.context.rotate()旋转
4.this.context.drawImage() // 画图 ,接收ImageBitmap 对象 如:new ImageBitmap(src),起始点坐标,大小宽高)
5.this.context.restore() 回复状态
二十五、动画
animation动画
那个位置需要使用在哪位置添加
格式:
.animation({
duration: 5 * 1000, //多久执行完成
curve: Curve.Linear, // 不添加默认这个类型
onFinish: () => {
//动画完成触发
promptAction.showToast({ message: '执行完成' })
},
iterations: 1 // 默认一次,无限循环使用-1
})
animateTo显示动画
格式:
Button("按钮")
.onClick(() => {
animateTo({
// 当页面重新渲染则获执行动画效果
duration: 2 * 1000,
curve: Curve.Linear,
onFinish: () => {
// 执行完成事件
}
}, () => {
// 变更样式属性 宽高
this.width1 = 300
this.height1 = 200
})
})
Navigator转场动画,可以用于路径跳转
Navigator主要实现2个页面的跳转动画效果
格式:
// 类似于ppt的投影图片效果模式
Navigator({ target: "pages/index", type: NavigationType.Push }) { // 默认淡入淡出
Image($r("app.media.icon"))
}
pageTransition页面转场动画效果
pageTransition结合Navigator使用
在build()外部使用,用于动画进入和退出时的效果
格式:
pageTransition() {
PageTransitionEnter({ // 进入动画
duration: 5 * 1000,
curve: Curve.Ease
}).onEnter((type: RouteType, progress: number) => {
// progress 进度条
this.op = progress
})
.opacity(this.op)
.slide(SlideEffect.Top) // 控制进入方向
PageTransitionExit({ // 退出动画
duration: 2 * 1000,
curve: Curve.Linear }).onExit((type: RouteType, progress: number) => {
// progress 进度条
this.op = 1 - progress
})
.opacity(this.op)
.slide(SlideEffect.Top)
}
animateTo组件内动画
格式:当重新渲染时加载动画
@State isShow: boolean = true
build() {
Column({ space: 30 }) {
Button("组件内动画")
.onClick(() => {
animateTo({ duration: 3 * 1000, curve: Curve.Linear }, () => {
this.isShow = !this.isShow
})
})
if (this.isShow) {
Image($r("app.media.icon"))
.width("80%")
.height("80%")
.transition({
type: TransitionType.All,
scale: { x: 0.1, y: 0.1 }, // 缩放初始化
rotate: { angle: 180 * 10 } // 旋转角度
})
}
}
.width('100%')
.height('100%')
}
sharedTransition共享元素组件
当页面发生跳转,可以看到动画共用的效果,需要多个组件才可以使用
.sharedTransition(
'path', // 'path':是需要组件id保持一致
{
duration:3*1000,
curve:Curve.Linear
})
motionPath路径动画
格式:
.motionPath({ path: 'Mstart.x start.y L00 200 L500 500 L 500 0 Lend.x end.y',
from: 1.0, //从哪到哪,没看出来什么区别
to: 1.0
})
例:
@Component
struct MotionPathDome {
@State isShow:boolean = false
build() {
Column() {
Button("按钮")
.onClick(() => {
animateTo({
duration: 3 * 1000,
curve: Curve.Linear
}, () => {
this.isShow =!this.isShow
})
})
Image($r("app.media.icon"))
.width(this.isShow?"30%":"10%")
.height(this.isShow?"30%":"10%")
.motionPath({ path: 'Mstart.x start.y L00 200 L500 500 L 500 0 Lend.x end.y',
from: 1.0, //从哪到哪
to: 1.0
})
}
.width('100%')
.height('100%')
}
}
二十六、多媒体
Video视频
定义控制器:
private controller: VideoController = new VideoController()
Video({
src: $rawfile('mda-qdr9m6wqyishnfnr.mp4'), //视频的数据源
previewUri:'图片的数据源' // 视频未播放时的预览图片路径,默认不显示图片。
currentProgressRate:PlaybackSpeed.Speed_Forward_1_00_X, // 默认
controller: this.controller // 设置视频控制器,可以控制视频的播放状态。
})
.muted(false) // 是否静音。默认值:false 不静音
.autoPlay(true) // true 自动播放
.controls(true) // 是否显示原有的控制栏
.onPrepared((event) => { // 播放之前执行
this.max = event.duration // 获取视频总时长
})
.onUpdate((event) => { // 获取当前指定的长度
this.current = event.time
})
private controller: VideoController = new VideoController()
控制器常见方法:
播放:this.controller.start()
暂停:this.controller.pause()
结束: this.controller.stop()
重播:reset()
是否全屏播放:requestFullscreen(true/false)
设置当前进度:this.controller.setCurrentTime(this.current)
扩展
number.toString().padStart(2, '0') // 比如:当月份的长度不足2位数时, 校验长度是否够2个,否则前面使用0填充
// 随机生成UUID
import util from '@ohos.util';
let uuid:string = util.generateRandomUUID()
@Preview:当为组件时,可以使用注解进行显示预览功能
项目启动注意事项或者检查(**会导致模拟启动不起来等其他情况)
1.确定首页跳转路径: src/main/ets/entryability/EntryAbility.ts 中的windowStage.loadContent('首页url')
2.查看软件图标和名称是否修改: src/main/module.json5 中的 icon 和 label 值
3.当引入网络资源需要权限添加配置: src/main/module.json5 在module添加
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
规范项目结构
版权声明:本文标题:HarmonyOS系统应用开发基础入门 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1729706283a1210766.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论