HarmonyOS知识点

HarmonyOS应用模型Stage&FA 、ArkTS、ArkUI
Stage模型:
Module - UIAbility - Page - component

装饰器@Entry、@Component、@CustomDialog、@State、关键字struct、函数build()

系统组件(Text Column Row Scroll)、自定义组件 、组件复用、组件事件、组件属性、组件状态(能够对对象深度响应式改变)

在arkUI中,我们的内容如果超过了屏幕显示,则不会显示滚动条,需要使用Scroll来包裹
需要注意的是: 该组件滚动的前提是主轴方向大小小于内容大小。子组件不要设置高度,否则不能滚动

样式(链式&枚举)
vp和适配(伸缩布局,网格系统,栅格系统)
vp 是鸿蒙默认单位,和屏幕像素有关,最终表现视觉大小在任何设备一致
1、伸缩 layoutWeight(flex: number) 占剩余空间多少份,可以理解成CSS的 flex: 1
2、内容等比例缩放-可以使用aspectRatio属性设置宽高比

Image的四种使用方式

1、使用本地图片  Image('/assets/test.jpg')  /src/main/ets/assets/test.jpg
2、使用资源引入 Resource 类型  Image(\$r("app.media.test"))  /src/main/resources/base/media/test.jpg
3、采用原始文件引入  Image(\$rawfile('test.jpg'))  /src/main/resources/rawfile/test.jpg
4、引用网络图片 Image("https://...")   在模拟器中需要在module.json5文件中配置网络权限才能显示

垂直水平居中
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)

@Styles复用、@Extend复用

StateStyle(正常态normal,按压态pressed,获焦态focused,禁用态disabled)样式抽离只能抽离到组件内,不能抽离到全局

if else 创建销毁,opacity隐藏后占位置,visibility: Visibility.Hidden占位置, visibility: Visibility.None不占位置

数据父传子,事件父传子实现数据子传父

// 把子组件的item传给父组件
// 子
public item: Partial<ReplyItem> = {} // 非响应式数据
public changeLike: (params: ReplyItem) => void = () => {}
.onClick(()=>{this.changeLike(this.item as ReplyItem)
})
// 父
MainItem({item: item, changeLike: (obj: ReplyItem)=>{this.changeLike(obj)
}})
changeLike(obj: ReplyItem){......
}
// Partial 把需要传入的对象ReplyItem内的属性变为可选的(可传可不传)
public item: Partial<ReplyItem> = {} // 非响应式数据
// this.item 属性都是可选的,使用 as 规避类型错误,强制认为ReplyItem内有属性有值
this.changeLike(this.item as ReplyItem)

构建函数
@Builder - 自定义构建函数,复用单元,对于修改响应式数据只能修改按引用传递(obj)不能按值传递参数(string)

@BuilderParam 类似于Vue中slot插槽的作用,只能应用在Component组件中,不能使用Entry修饰的组件中使用。尾随闭包、

@Builder setBtn() {Button('你好')
}
Card({getContent: this.setBtn})
// Card
@BuilderParam getContent: () => void = () => {}
this.getContent()

@Prop单向数据流(父变子变,子变父不变)
@Link双向绑定 注意:Link修饰的数据必须得是最外层的 State数据,不能传变化后的,比如forEach里的参数item就不允许传

状态共享-后代组件
父@Provide定义 和 子@Consume接收

@Watch监听

@Observed修饰类与@ObjectLink接收,可以解决@Link弊端,如上面提到的forEach里的参数item就不允许传到@link,此时就可以传item了
@ObjectLink不能整体赋值,只能对里面的属性赋值

@ObjectLink upClass: UploadClass
@Observed
class UploadClass {images: ImageList[] = []
}
多层state修改
this.user.address.city = "廊坊"
this.user.address = new IAddressModel(this.user.address)
// border边框线
.border({width: 1,color: {left: Color.White,right: Color.White,top: Color.White,bottom: Color.Black},
})
// 渐变色
.linearGradient({angle: '94deg',colors: [[$r('app.color.color_FF852E'), 0], [$r('app.color.color_FF5F2E'), 99]]
})
// 最大宽 高
.constraintSize({maxWidth: '',maxHeight: ''
})
// 实现软键盘弹出后,整体布局不变
.expandSafeArea([SafeAreaType.KEYBOARD]) 
// 键盘避让
windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE)
// 关闭输入法软键盘
inputMethod.getController().stopInputSession()
// 主动调起软键盘
focusControl.requestFocus('input_id')

LocalStorage、AppStorage

持久化的数据
PersistentStorage.PersistProp<string>("user_cart", "[]")
页面生命周期
aboutToAppear: 页面初始化触发一次。
onPageShow: 页面每次显示时触发。
onPageHide: 页面每次隐藏时触发一次。
aboutToDisAppear: 页面销毁时触发一次。
onBackPress: 当用户点击返回按钮时触发。自定义组件生命周期
aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
aboutToDisappear:在自定义组件即将析构销毁时执行UIAbility生命周期
UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态
创建到销毁的过程
onCreate - onWindowStageCreate- onForeground - onBackground - onWindowStageDestroy - onDestroy

ability通信

// abilityA - 页面
const context = getContext(this) as common.UIAbilityContext
let want: Want = {bundleName: 'com.example.helloworld', // 包名 AppScope/app.json5 app.bundleNameabilityName: 'HeimaPayAbility', // HeimaPay/src/main/module.json5moduleName: 'HeimaPay',parameters: {order_id: Date.now()}
}
const result = await context.startAbilityForResult(want) //拉起另外一个ability并接收另外一个ability的返回值
const params =   result.want.parameters as ResultParams
type  ResultParams = Record<string, boolean> // Record相当于Map,定义一个键值对类型
// abilityB
type AbilityParams = Record<string, number>
onCreate(want: Want, launchParam) {const params = want.parameters as AbilityParams// 将参数设置到AppStorageAppStorage.SetOrCreate<number>("order_id",  params.order_id )
}
// abilityB - 页面
// 销毁当前的ability 将支付结果告诉调用我的人
const context = getContext(this) as  common.UIAbilityContext
context.terminateSelfWithResult({resultCode: 1,want: {abilityName: 'EntryAbility',bundleName: 'com.example.helloworld',moduleName: 'entry',parameters: {paySuccess: true}}
})

通知发布,通知唤起ability

// 发起一个通知
notificationManager.publish({content: {contentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,normal: {title: "温馨提示",text: "您有一个新订单",additionalText: "订单提醒"}},wantAgent: await wantAgent.getWantAgent({ // 点击通知拉起一个abilitywants: [{bundleName: "com.example.mylogisticsapp01", //包名在最上面AppScope里 app.json5abilityName: "ListenAbility",parameters: {order_id: Date.now()}}],operationType: wantAgent.OperationType.START_ABILITY,requestCode: 0})
})

路由传值

路由模式
● Standard:标准实例模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。
● Single:单实例模式。即如果目标页的url在页面栈中已经存在同url页面,则离栈顶最近的同url页面会被移动到栈顶,并重新加载;如果目标页的url在页面栈中不存在同url页面,则按照标准模式跳转。
简单理解
1. Standard-只要你push,页面栈里面就会加一项,不管之前加没加过
2. Single- 你之前加过,不会加新的页面,会把你之前加过的页面加出来
router.pushUrl({url: 'pages/CarRecord/CarRecord',params: {id: this.taskDetailData.id}
})
// 接收
const params = router.getParams() as CommonRouterParams
if (params && params.id) {}
// 类型
export class CommonRouterParams {id?: string = ''
}

震动

import vibrator from '@ohos.vibrator';
vibrator.startVibration({ duration: 300, type: 'time' }, { id: 0, usage: 'touch' })

声音播放

AVPlayerClass.playAudio("success.wav", getContext(this)) // 单例 音频播放都通过这一个单例 也不需要new
// 播放类  单例
export class AVPlayerClass {// 调用之前不希望创建avPlayer  所以给个联合类型null  默认是nullstatic avPlayer: media.AVPlayer | null = nullstatic audioName: string = "" //存储当前的音频的名称static isSettingBack: boolean = false // 是否设置过回调 因为针对某一个player只能设置一次回调// 提供一个只播放音乐的静态方法static async playAudio(audioName: string, context: Context) {if (!AVPlayerClass.avPlayer) {AVPlayerClass.avPlayer = await media.createAVPlayer()}//如果audio有值if (audioName) {// 将这个值对应的音频文件读过来给avPlayer的fdSrcAVPlayerClass.audioName = audioNameAVPlayerClass.setAvPlayerAudio(context)}}// 注册avplayer回调函数static setAVPlayerCallback() {// seek操作结果回调函数AVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {// console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);AVPlayerClass.avPlayer!.play()//回到0秒后 才播放   播完了就会走到 case 'completed': 需要重置})// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程// 状态机变化回调函数AVPlayerClass.avPlayer!.on('stateChange', async (state: string, reason: media.StateChangeReason) => {switch (state) {// case 'idle': // 成功调用reset接口后触发该状态机上报//   console.info('AVPlayer state idle called.');//   AVPlayerClass.avPlayer.release(); // 调用release接口销毁实例对象//   break;case 'initialized': // avplayer 设置播放源后触发该状态上报console.info('AVPlayer state initialized called.');AVPlayerClass.avPlayer!.prepare();//准备播放           ! 是类型的非空断言break;case 'prepared': // prepare调用成功后上报该状态机console.info('AVPlayer state prepared called.');AVPlayerClass.avPlayer!.seek(0); // 调用播放接口开始播放  //将音频的播放进度挪到0的位置break;case 'playing': // play成功调用后触发该状态机上报break;case 'paused': // pause成功调用后触发该状态机上报console.info('AVPlayer state paused called.');break;case 'completed': // 播放结束后触发该状态机上报console.info('AVPlayer state completed called.');AVPlayerClass.avPlayer.reset(); // 调用reset接口初始化avplayer状态  //重置了break;case 'stopped': // stop接口成功调用后触发该状态机上报console.info('AVPlayer state stopped called.');break;case 'released':console.info('AVPlayer state released called.');break;default:console.info('AVPlayer state unknown called.');break;}})}static async setAvPlayerAudio(context: Context) {//AVPlayerClass.audioNamelet fileDescriptor = await context.resourceManager.getRawFd(AVPlayerClass.audioName)let avFileDescriptor: media.AVFileDescriptor ={ fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };if (!AVPlayerClass.isSettingBack) {// 设置回调 回调只能设置一次AVPlayerClass.setAVPlayerCallback()}if (AVPlayerClass.avPlayer) {// 拿到了资源 赋值给播放器的src属性  意味着会走回调AVPlayerClass.avPlayer.fdSrc = fileDescriptor;}}
}

动画
显式动画(animateTo)和属性动画(animation)

.onClick(() => {animateTo({duration: 500}, () => {this.showCom = !this.showCom})
})
Image($r("app.media.test")).transition({type: TransitionType.Insert,rotate: {angle: -360}}).transition({type: TransitionType.Delete,rotate: {angle: 360}})

混合开发sdk通信

Web({ src: $rawfile('location.html'), controller: WebSdkClass.controller! }).height('100%').width('100%').javaScriptProxy({object: this.webSdk,name: 'shenling',methodList: ['alert', 'toast', 'getLocation', 'receiveData'],controller: WebSdkClass.controller!})
// location.html
shenling.receiveData("search_list",JSON.stringify(result?.poiList?.pois || []))
// web_sdk.ets
export class WebSdkClass {static controller: Webview.WebviewController | null = nullstatic context: Context | null = nullalert(msg: string) {AlertDialog.show({message: msg})receiveData(eventName: string, json: string){WebSdkClass.context?.eventHub?.emit(eventName, json)}
}
回答: 
鸿蒙原生和h5通信有大概两种方式
1. 通过消息机制推送,类似于前端的postMessage的跨域通信,首先通过原生端的webviewController进行创建通信端口, createMessagePorts, 该方法会创建两个端口,一个用作原生端,一个用作h5端,然后通过webviewController将其中一个端口通过postMessage发送到h5端,h5端用onmessage来接收该端口,并全局缓存,此时,h5端用接收的端口发送消息给原生端,原声端用自己剩余的端口进行onMessage接听消息,此时就可以实现双向通信
2. api调用的形式原生端可以通过javascriptProxy给h5页面注入可用的sdk应用方法集合,在h5完成初始化后,可以直接调用原生的方法,这是h5调用原生原生端也可以直接调用h5端的方法 runJavascript,在这个方法里面传入方法调用传参数就可以
需要注意的点: 如果原生端的sdk方法是个异步方法,在h5端无法及时得到结果,
此时需要再用原生反调h5进行传递结果

坑点
watch不能写在修饰符前面
prop只支持数字、字符串、布尔三种类型

总结:
● Column/Row
● Text/Button/TextInput
● Flex-List-带滚动条-Scroll(不要对子组件的宽和高进行设置,内部只能放一个子组件)
● 条件渲染(if else)/循环渲染(ForEach)
● State修饰符(声明响应式数据)- 驱动UI的更新-只会监听第一层数据

● State组件内状态
● Prop子组件修饰符-4.0 boolean/number/string- 单向数据流
● Link 子组件修饰符-双向数据流,所有类型都支持- 必须通过$前缀-(循环数据就没有办法传入)
● Provide和Consume 双向数据流-所有结构均支持
● Watch 可以监听State Link Prop ObjectLink的数据变化
● Observed和ObjectLink

● Link-双向
● Prop-单向
● Observed 和 ObjectLink- (肯定不能用在entry修饰的组件中)
● LocalStorage(UIAbility)-AppStorage-PersionStorage(写入磁盘-不能每次都直接运行)
PersionStorage来声明一下属性就可以保证该属性会被写入缓存
● StorageProp-StorageLink
● Http
● 嵌套更新数据的方式-Next

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

速盾:CDN是否支持屏蔽IP?

CDN&#xff08;内容分发网络&#xff09;是一种用于提高网站性能和可靠性的技术&#xff0c;通过将内容分发到距离终端用户更近的节点&#xff0c;减少了数据传输的延迟并提高了用户体验。在CDN中&#xff0c;屏蔽IP是一项重要的功能&#xff0c;可以帮助网站屏蔽无效或恶意请…

Linux修改/etc/hosts不起作用(ping: xxx: Name or service not known)的解决方法——开启NSCD

​ 问题描述 起因是我在实验室云资源池的一台虚拟机&#xff08;CentOS 8.5&#xff09;上的/etc/hosts文件中为Fabric网络节点的域名指定了IP&#xff1a; IP可以ping通&#xff0c;但是ping域名时提示ping: xxx: Name or service not known。 问题本身应该是Linux通用的&a…

OpenTelemetry 赋能DevOps流程的可观测性革命

原作者&#xff1a;天颇 原出处&#xff1a;微信公众号 乘云数字DATABUFF 原文地址&#xff1a;https://mp.weixin.qq.com/s/D_f31EBtLu7Rr0gahuF-bw 引言 在当今快节奏的软件开发和运维环境中&#xff0c;DevOps 已经成为主流&#xff0c;它通过整合开发和运维流程&#xff0…

学了Arcgis的水文分析——捕捉倾泻点,河流提取与河网分级,3D图层转要素失败的解决方法,测量学综合实习网站存着

ArcGIS水文分析实战教程&#xff08;7&#xff09;细说流域提取_汇流域栅格-CSDN博客 ArcGIS水文分析实战教程&#xff08;6&#xff09;河流提取与河网分级_arcgis的dem河流分级-CSDN博客 ArcGIS水文分析实战教程&#xff08;5&#xff09;细说流向与流量-CSDN博客 ArcGIS …

windows 和 linux检查操作系统基本信息

windows检查操作系统基本信息 systeminfolinux检查操作系统基本信息 获取系统位数 getconf LONG_BIT查询操作系统release信息 lsb_release -a查询系统信息 cat /etc/issue查询系统名称 uname -a

gitHub常用操作

gitHub常用操作 1、把项目拉下来2、添加上游仓库3、进入分支4、从上游仓库拉取更新 1、把项目拉下来 在对应项目的右上角点击fork&#xff0c;fork下来&#xff1a;将远程仓库复制到个人仓库 在创建好的分支文件夹下使用 git clone自己远程仓库下的http地址&#xff08;fork…

使用SaaS化的Aurora应用快速搭建私人ChatGPT助手

使用SaaS化的Aurora应用快速搭建私人ChatGPT助手 简介&#xff1a; Aurora是一个带UI且免费的GPT私人聊天助手&#xff0c;可切换GPT-3.5&#xff0c;4&#xff0c;4o等常用版本。用户可通过部署Aurora&#xff0c;快速打造自己专属的AI助手。阿里云计算巢已将Aurora打包为SaaS…

Android开发实战班 -网络编程 - Retrofit 网络请求 + OkHttp 使用详解

在现代 Android 应用开发中&#xff0c;网络编程是必不可少的一部分。Retrofit 是 Square 公司推出的一款类型安全的 HTTP 客户端库&#xff0c;简化了与 RESTful API 的交互。Retrofit 基于 OkHttp&#xff0c;并提供了简洁的接口定义和强大的功能&#xff0c;如异步请求、请求…

ASFSSA-VMD多策略改进的麻雀搜索算法优化变分模态分解

ASFSSA-VMD多策略改进的麻雀搜索算法优化变分模态分解 目录 ASFSSA-VMD多策略改进的麻雀搜索算法优化变分模态分解效果分析基本介绍程序设计参考资料效果分析 基本介绍 (创新独家)ASFSSA-VMD多策略改进的麻雀搜索算法优化变分模 态分解ASFSSA-VMD:优化VMD分解层数K和惩罚因子a…

Unity脚本基础规则

Unity脚本基础规则 如何在Unity中创建一个脚本文件&#xff1f; 在Project窗口中的Assets目录下&#xff0c;选择合适的文件夹&#xff0c;右键&#xff0c;选择第一个Create&#xff0c;在新出现的一栏中选择C# Script&#xff0c;此时文件夹内会出现C#脚本图标&#xff0c;…

【新华妙笔-注册/登录安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

Dart:字符串

字符串&#xff1a;单双引号 String c hello \c\; // hello c&#xff0c;单引号中使用单引号&#xff0c;需要转义\ String d "hello c"; // hello c&#xff0c;双引号中使用单引号&#xff0c;不需要转义 String e "hello \“c\”"; // hell…

使用vscode+expo+Android夜神模拟器运行react-native项目

1.进入夜神模拟器安装路径下的bin目录 2.输入命令&#xff0c;连接Android Studio 启动夜神模拟器后&#xff0c; 打开安装目录的bin文件夹执行下面的命令&#xff0c;只需执行一次&#xff09; nox_adb.exe connect 127.0.0.1:62001adb connect 127.0.0.1:62001 3.运行项目…

从0安装mysql server

安装 MySQL Server 首先,你需要在 Ubuntu 上安装 MySQL 服务器。运行以下命令来安装:sudo apt update sudo apt install mysql-server安装完成后,MySQL 服务会自动启动。你可以通过以下命令检查 MySQL 服务是否正在运行: sudo systemctl status mysql如果 MySQL 正在运行,…

自动计算机视觉功能技术方向

近年来&#xff0c;随着自动计算机视觉功能的不断发展&#xff08;如跟踪、目标/活动识别等&#xff09;的技术方向&#xff0c;这些技术在无人机应用领域中的重要性也日益凸显。同时&#xff0c;得益于低成本商用无人机的日益普及&#xff0c;这些技术得到了快速的推广和应用。…

Linux进阶:软件安装、网络操作、端口、进程等

软件安装 yum 和 apt 均需要root权限 CentOS系统使用&#xff1a; yum [install remove search] [-y] 软件名称 install 安装remove 卸载search 搜索-y&#xff0c;自动确认 Ubuntu系统使用 apt [install remove search] [-y] 软件名称 install 安装remove 卸载search 搜索-y&…

C语言 蓝桥杯某例题解决方案(查找完数)

蓝桥杯原题&#xff1a; 一个数如果恰好等于它的因子之和&#xff0c;这个数就称为“完数”。例如6 1 2 3.编程找出1000以内的所有完数。 这个题没有很大的难点&#xff0c;与我们上一个解决的问题“质因数分解”不同&#xff0c;它不需要判断因数是否是质数&#xff0c;因此…

linux先创建文件夹后指定创建文件夹用户

1、创建文件夹&#xff0c;然后创建用户并指定用户目录&#xff0c;然后修改目录所有权给该目录 # 创建 /home/test 目录 mkdir /home/test # 设置权限&#xff08;确保有适当的读写权限&#xff09; chown root:root /home/test chmod 700 /home/test # 创建 xl 用户并指定家…

Gin 框架中的表单处理与数据绑定

Gin 框架中的表单处理与数据绑定 在Web应用开发中&#xff0c;表单是用户与服务器交互的重要手段。Gin框架作为一款高效、简洁的Go语言Web框架&#xff0c;为表单处理提供了便捷的支持&#xff0c;包括数据绑定、验证等功能。本文将详细介绍如何使用Gin框架处理表单数据&#…

记录下,用油猴Tampermonkey监听所有请求,绕过seesion

油猴Tampermonkey监听所有请求&#xff0c;绕过seesion 前因后果脚本编写 前因后果 原因是要白嫖一个网站的接口&#xff0c;这个接口的页面入口被隐藏掉了&#xff0c;不能通过页面调用&#xff0c;幸好之前有想过逆向破解通过账号密码模拟登录后拿到token&#xff0c;请求该…