ArkTs进阶
arkts进阶,进一步详解字符串、数组、运算符、分支结构、循环结构、常见事件方法、状态管理、装饰器、泛型定义以及模块化方法
字符串
加号两边只要有字符串,就是拼接的作用。
模版字符串(xxx
)主要用于拼接多个变量的字符串拼接
let name: string = 'Tom'
console.log(`姓名:${name}`)
类型转换
1.字符串转数字
Number():字符串 直接转数字,转换失败返回NaN(字符串中包含非数字)(常用)
parseInt():去掉小数部分 转数字(取整),转换失败返回NaN
parseFloat():保留小数部分转数字,转换失败返回NaN (用得少)
需要是计算,必须加号都是数字 -> 字符串类型,转成数字
2.数字转字符串
数据.toString() 原样转字符串
数据.toFixed(保留几位小数) 四舍五入(多用来展示几位小数)
运算符
算数运算符:+ - * / %
赋值运算符:+=、-=、*=、/=、%=
一元运算符:++ --
比较运算符:> >= < <= == != ===(严格相等,只有数值和类型都相等,结果才会为true)
逻辑运算符:&&、||、! (与或非)
运算符优先级(由高到低):小括号、一元(++,--,!)、算数、比较(>,>=,<,<=)、比较(==,!=)、逻辑运算符(先&&后||)、赋值
数组
let names:string[] = ['aa','bb','cc']
添加元素:
① 往开头新增:unshift(新增的值) 返回操作后的数组长度
② 往结尾新增 push(新增的值) 返回操作后的数组长度
删除元素:
① 从开头删除 shift,返回删除的项
② 从结尾删 pop,返回删除的项
记:开头(S),结尾(p)
任意位置添加/删除数组元素(splice)
语法:数组名.splice(操作的起始位置,删除的个数,新增元素1,新增元素2,...)
from方法用于生成测试数组,可选长度,里面没有内容。
Array.from({ length: 10 })
对象数组:
1.约定接口(对象的类型)
interface Student {
stuId: number
name: string
gender: string
age: number
}
2.基于接口创建对象数组
let stuArr: Student[] = [
{stuId: 1, name:'小丽', gender: '女', age: 12},
{stuId: 2, name:'小红', gender: '女', age: 13},
{stuId: 3, name:'小明', gender: '男', age: 13},
{stuId: 4, name:'小刚', gender: '男', age: 12},
{stuId: 5, name:'小强', gender: '男', age: 13},
]
3.使用(通过下标访问)
console.log('小红:', stuArr[1].name)
console.log('小红:', JSON.stringify(stuArr[1]))
同样支持for...of,普通for进行遍历
注:
包括对象的复杂数据,如果想要在日志中打印,需要调用一个方法,转成字符串
JSON.stringify(复杂类型) —— 对象/数组
对象数组的情况需要更新,需要修改替换整个对象。(不可直接修改对象数组中的某一个属性值,否则不会变!!!)
剩余参数(展开运算符)
可以将 函数 或 方法 中一个不定数量的参数表示为一个数组
语法:...数组名:数组类型
function sum (n1: number, n2: number, ...argsArr: number[]){
console.log('剩余数组', argsArr)
//如果有剩余的参数,就继续使用剩余参数。若没有剩余参数即只使用前面的参数
注:展开运算符只能用在数组上!
分支结构
三种语句执行结构:顺序结构、分支结构、循环结构
1.单分支(满足条件,就会执行一段代码)
2.双分支(满足条件,会执行A代码,不满足,执行B代码)
3.多分支:可以解决多种分支的情况
4.switch分支
一般用于精确匹配,不同的值执行不同代码
let fruit: string = '苹果'
switch (fruit){
case '苹果':
console.log('苹果价格:2.8元一斤')
break //注意:break不可漏,否则会继续执行下一条case
case '香蕉':
console.log('香蕉价格:5.5元一斤')
break
default:
console.log('提示:该水果不存在')
}
5.三元表达式
语法:条件?条件成立执行的表达式:条件不成立执行的表达式
注:除了switch,其余条件控制亦可控制UI界面的显示
循环结构
while循环:
let num:number = 1
while (num <= 100){
console.log('打印:',num)
num++
}
for循环:
for(初始值;循环条件;变化量)
{
重复执行的代码(循环体)
}
for of 循环:
语法:for(let item of 数组名) {}
for...of: 在...之中,进行循环
item: 声明的一个变量,用来在循环的时候接受 每一个数组元素
ForEach 渲染控制:
语法:ForEach(arr,(item,index) => {})
ForEach 可以基于数组的个数,渲染组件的个数(简化代码)
item是需要遍历的每一项,index是下标
break和continue:
break:终止整个循环(后面的循环不执行了)
continue:退出当前一次循环的执行,继续执行下一次循环
常见事件方法
1.onclick
语法:onClick( (参数) => { 事件内容 } )
2.对话框 alertDialog
AlertDialog.show({
message: 'xxx'
})
3.Math方法
求随机数:Math.random ([0,1)的小数)
向下取整:Math.floor
状态管理
如果希望构建一个动态的、有交互的界面,就需要引入“状态”概念
点击交互出发了文本状态变更,状态变更 引起了 UI渲染
普通变量,只能在 初始化 时渲染,后续变化了,也不会引起更新。
状态变量,被装饰器修饰,值的改变,会[自动]引起 界面的更新
注意:
组件外变量不需要this,即可访问。而组件内变量必须用this.xxx访问。
组件内的普通变量,不能加修饰前缀,如let。
组件内状态变量需加上@State装饰器修饰!
状态变量中必须加上数据类型,不然会报错!
@State
注意:不是状态变量的所有更改都会引起刷新。只有可以被框架观察到的修改才会引起UI刷新。
1.boolean、string、number类型时,可以观察到数值的变化
2.class或者Object时,可观察 自身的赋值 的变化,第一层属性赋值的变化,即Object.keys(observedObjecct)返回的属性。见第三条。
3.复杂类型:class或者Object时,第一层随便改,嵌套需要进行整个嵌套的对象替换
@prop
装饰的变量可以和父组件建立单向的同步关系
@Prop 装饰的变量是可变的,但是变化不会同步回其父组件
子组件,可以修改到prop传值,但修改的更新不会同步到父组件。通常不会直修改 prop 传值,父组件的状态一旦变化,会自动向下同步,修改就被覆盖了。
this指向问题:
若在子组件中希望父组件同步更新,需要调用父组件传递过来的方法。
父组件必须使用箭头函数
如果父组件没有用箭头函数,意味着this指向子组件。
在普通函数内部,this通常指的是当前执行上下文的对象。
箭头函数没有自己的this绑定,它会从外围作用域继承this值。
使用箭头函数的好处,可以使用外部环境的this,不受传递过去后的执行环境影响
通常为了实现双向同步,一般不会使用此方法,直接使用@Link装饰器即可。
@Link
使用@Link 可以实现父组件和子组件的 双向同步
使用步骤:
1.将父组件的状态属性 传递给子组件
2.子组件通过 @Link修饰 即可
注:子组件中Link声明的变量不可以赋值!
@Provide和@Consume
将数据传递给后代,和后代的数据进行 双向同步 (跨层级双向同步)
步骤:
1.将父组件的状态属性使用@Provide修饰
2.子组件通过@Consume修饰
注:
子组件变量名必须和父组件统一!
子组件中Consume声明的变量不可以赋值!
使用Provide和Consume时,在父组件调用子组件时,无需在子组件括号内写传入的参数对象,而是要保证父子变量名统一即可实现传递。
装饰器
@Extend 样式重用
可以扩展 特定组件 的 样式、事件,实现 复用 效果
//头部定义
@Extend(组件名)
function 函数名(参数1,参数2){} //可传递参数
可在容器中对应的组件使用函数名调用定义的样式。
@Styles 通用样式
抽取通用属性、事件(只能抽取通用的样式)
//开头定义
@Styles function commonStyles() {
.width(100)
.height(100)
//注意:组件内定义的元素,全局不可读
}
注:
styles修饰的不支持传参!
组件内Styles修饰的方法名前不可加function
@Component 自定义组件
概念:由框架直接提供的称为 系统组件,由开发者定义的称为 自定义组件
系统组件:如Row、Text......
自定义组件可以使大的页面,拆分成很多小的部分
@Component
struct MyHeader{
}
1.通用样式事件
自定义组件可以通过点语法,设置 通用样式,通用事件
注:给组件设置属性是给外层添加的,而不是内部根组件(如Row)添加的。且内部事件的优先级高于外部事件
2.成员函数变量
除了必须要实现build()函数外,还可以定义其他的成员函数,以及成员变量
@Component
struct MyPannel {
//成员变量 - 数据 —— 可外部传入覆盖
@State title: string = '默认的大标题'
//成员变量 - 函数 —— 可以外部传入覆盖
getMore = () => {
AlertDialog.show({
message: '查看更多'
})
}
//成员函数 —— 不可以外部传入覆盖
sayHi(){
AlertDialog.show({
message: '打招呼,你好!'
})
}
build(){}
}
注意:在使用自定义组件时,在括号内可以传入参数,覆盖自定义的变量,但是不能对函数进行覆盖,只能对函数变量进行覆盖。
MyPannel({
title: '小米有品众筹',
getMore(){
AlertDialog.show({
message: '查看7款众筹'
})
}
})
@Builder 轻量级封装
自定义构建函数(结构、样式、事件)
注意:
1.builder只能使用组件内的状态
2.可传递参数
@Builder
function navItem(icon: ResourceStr, txt: string) {
Column({ space: 10 }) {
Image(icon)
Text(txt)
}
}
全局定义调用时直接使用方法名调用,在组件内定义时,必须用this.方法名调用。
@BuilderParam 传递UI
利用 @BuilderParam 构建函数,可以让自定义组件 允许外部传递UI
1.定义构建函数
定义 BuilderParam 接收外部传入的UI,并设置默认值
@Component
struct SonCom{
//在自定义组件内使用
@BuilderParam ContentBuilder: () => void = this.defaultBuilder
//必须要写默认的Builder进行初始化
@Builder
defaultBuilder() {
Text('默认的内容')
}
build(){
//2.使用构建函数,构建结构
Column(){
this.ContentBuilder()
}
}
}
2.使用此自定义组件,并且传入UI结构
Column(){
SonCom() { //若没有花括号,则表示不传结构,那么使用的就是上面默认的结构
//直接传进来(尾随闭包)
Button('传入的结构')
}
}
3.多个 BuilderParam 构建函数
子组件有多个BuilderParam,必须通过参数的方式来传入
即多个结构UI需要定制的场景使用
@BuilderParam tBuilder: () => void = this.tDefaultBuilder
@BuilderParam cBuilder: () => void = this.cDefaultBuilder
@Builder tDefaultBuilder() {
Text('我是默认大标题')
}
@Builder cDefaultBuilder() {
Text('我是默认内容')
}
使用时,传入多个BuilderParam时,不可再使用尾随闭包,必须通过参数传入!
@Builder ftBuilder(){}
@Builder fcBuilder(){}
MyCard({ //若有多个结构UI,要通过参数的方式传入,不能通过尾随闭包传递!
tBuilder: this.ftBuilder,
cBuilder: this.fcBuilder
})
泛型(广泛的类型)
泛型可以让 函数 等,与多种 不同的类型 一起工作,灵活可复用
简单说:类型可变(类型可当做参数传递)
function 函数名<Type>(形参:Type): 返回值类型{
return 形参
}
调用时,使用:函数名<Type>(实参)
注:调用时类型名最好加上,方便知道传入的是什么类型
如下注意区分:
function test<T>(arr: T[]): number{} //这里T是表示传入的是数组,但是什么类型的数组不一定。
test<number>([1,2,3]) //调用时候,<>中的要填写number,表示T是number型数组
function test2<T>(arr: T): number{}//这里T是表示传入的可以是任何类型,不一定是数组。
test2<number>(3) //这里T可以是number类型
test2<number[3]>([1,2,3]) //这里T也可以是number型数组
约束泛型:
给传递的类型参数,添加限制(泛型约束)
interface ILength {
length: number
}
function fn<T extends ILength>(param: T){ //传入的类型必须要有 接口中的属性
console.log('',param.length)
}
fn<string>('abc') //这里字符串类型有length属性,可以传入
多个泛型变量
可以传递多个类型参数。
泛型接口
定义接口的时候,结合泛型定义,就是泛型接口
//定义接口
interface IdFunc<T>{
//约定有两个方法(id类型不定,可能是string或number)
//1. 传入 id 值, 就返回 id 值
//2. 返回一个 ids 数组
id: (value: T) => T //类型都可以用T
ids: () => T[]
}
//实现接口
let obj: IdFunc<number> = {
id(value: number){
return value
},
ids() {
return [1,2,3]
}
}
泛型类
//定义类的时候,配合泛型一起定义
class Person<T> {
id: T
constructor(id: T) {
this.id = id
}
getId (): T {
return this.id
}
}
let p: Person<number> = new Person<number>(10)
console.log(p.getId().toString())
模块化
模块化:把一个大的程序,拆分 成若干个小的模块,通过 特定的语法, 可以进行任意组合
ArkTS中,每个ets文件,都可以看做是一个模块
导入和导出
默认导出导入
默认导出:指一个模块,只能默认导出 一个值 或 对象。使用时,可以自定义导入名称。
1.默认导入
路径:查找文件时,从起点到终点的路线
相对路径:从当前文件出发查找目标文件
export default xxx
import xxx from 'xxx'
2.按需导入
按需导出:指一个模块,可以按照需要,导出多个特性
按需导入的名称必须和导出的名称一致,花括号中名称顺序可以不固定。(若希望换名字,则需要使用as引用别名)
//导出
export let price: number = 1
export let price2: number = 2
//导入
import {price,price2} from 'xxx'
3.全部导入
将所有的按需导入,全部导入进来 ,导出部分不需要调整,调整导入的语法即可
import * as module from xxx '../xx' //‘*’不能当变量用,必须as一个别名
注:导出时可以一次性导出多个特性
export {name1,name2,name3}
- 上一篇: ArkTs基础(常变量及基本类型)
- 下一篇: 没有了