版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
项目2:ArkTS语言HarmonyOS优选的主力应用开发语言——ArkTS围绕应用开发在TypeScript生态基础上做了进一步扩展,保持了TS的基本风格,同时通过规范定义强化开发期静态检查和分析,提升程序执行的稳定性和性能。本项目将详细讲解ArkTS语法与ArkUI框架的基础知识。导学课程导学与目标概览ArkTS在UI开发框架(ArkUI)中主要扩展了三大能力:以声明式UI为主体的基本语法、多维度状态管理机制以实现数据和UI的联动、以及UI渲染控制能力。本项目将围绕这三大核心能力展开系统学习。🎯知识目标掌握ArkTS语言和开发特性掌握ArkUI框架的组件分类与声明式开发范式理解状态管理机制(@State/@Prop/@Link)及其在数据驱动UI中的应用熟悉条件渲染(if/else)与循环渲染(ForEach)的实现原理掌握@Extend样式扩展、@Builder构建函数和自定义组件的封装方法理解组件级与应用级状态管理的区别与适用场景掌握组件生命周期的管理与业务逻辑集成💪能力目标能熟练运用ArkTS进行开发调试能运用ArkTS声明式语法构建复杂UI界面能根据业务需求实现条件渲染与循环渲染能合理运用生命周期方法管理资源加载与释放能通过阅读文档实现跨组件状态共享🌟素质目标培养独立分析问题、解决问题的能力培养科学严谨的学习、工作态度养成良好的职业素养任务1ArkTS语言介绍应用的核心驱动是开发语言。HarmonyOS采用自有的ArkTS语言,是开发鸿蒙应用的基本工具。本任务针对ArkTS的关键核心语法进行介绍,利用ArkTS语言构建一个商品数列列表,并打印价格最低的商品信息。2.1ARKTS的简介从TypeScript到ArkTSArkTS兼容TS/JavaScript(简称JS)生态,开发者可以使用TS/JS进行开发或复用已有代码。从TypeScript到ArkTS的适配遵循以下核心规则:1强制使用静态类型程序中变量的类型确定,编译器可以验证代码的正确性,从而减少运行时的类型检查,有助于性能提升。2禁止运行时改变对象布局为实现最大性能,ArkTS要求在程序执行期间不能更改对象布局。3限制运算符语义为获得更好的性能并鼓励开发者编写更清晰的代码,ArkTS限制了一些运算符的语义。例如,一元加法运算符只能作用于数字,不能用于其他类型的变量。4不支持Structuraltyping对Structuraltyping的支持需要在语言、编译器和运行时进行大量的考虑和仔细的实现,当前ArkTS不支持该特性。ArkTS的UI能力ArkTS在UI开发方面提供了三大核心能力,构成了HarmonyOS应用界面开发的完整体系:基本语法能力ArkTS提供声明式UI、组件及扩展能力,构成UI开发核心。开发者可以用接近自然语义的方式描述界面结构。状态管理能力ArkTS支持多层次(组件内、跨组件、全局、跨设备)数据传递(单向/双向),实现数据UI联动。渲染控制能力ArkTS支持条件渲染、循环渲染和数据懒加载,灵活控制UI组件的显示与生成。2.2数据与运算数据类型、变量与运算ArkTS数据的定义和运算是应用的核心结构与语法。本节介绍基于ArkTS语言的数据类型、变量和变量的运算。在学习调试过程中,可以使用console.log日志打印方法查看与调试数据。//日志打印格式console.log(日志字符串)console.log('HelloWorld');类型与变量ArkTS通过声明引入变量、常量、函数和类型。变量声明(let)以关键字let开头的声明引入变量,该变量在程序执行期间可以具有不同的值。声明时可以赋初始值,也可以在后续时刻赋值。letbianliang:string='hello';bianliang='hello,world';常量声明(const)以关键字const开头的声明引入只读常量,该常量只能被赋值一次,对常量重新赋值会造成编译时错误。constchangliang:string='hello';//changliang='hello,world';//报错基本数据类型基本数据类型包括number、boolean、string等简单类型,可以准确地表示单一的数据类型。基本类型确保数据在存储和访问时是直接的,比较时直接比较其值。number类型任何整数和浮点数都可以被赋给此类型的变量。数字字面量包括整数字面量和十进制浮点数字面量。整数字面量类别:十进制整数:0、117、-345十六进制整数(0x开头):0x1123、0x00111、-0xF1A7八进制整数(0o开头):0o777二进制整数(0b开头):0b11、0b0011、-0b11浮点字面量:包含十进制整数、小数点、小数部分,以及可选的以"e"或"E"开头的指数部分。letn1=3.14;letn2=.5;letn3=1e2;boolean类型由true和false两个逻辑值组成,通常在条件语句中使用。letisDone:boolean=false;if(isDone){console.log('Done!');}string类型代表字符串序列,可以使用转义字符来表示字符。字符串字面量由单引号(')或双引号(")括起来,还有用反向单引号(`)括起来的模板字面量。lets1='Hello,world!\n';leta="Success";lets3=`Theresultis${a}`;引用数据类型ArkTS中的引用类型(如对象、数组和函数等)是通过引用访问的复杂数据结构。对象和数组可以包含多个值或键值对,函数则可以封装可执行的代码逻辑。引用类型在内存中通过指针访问数据,修改引用会影响原始数据。Object类型所有引用类型的基类型。任何值(包括基本类型的值,会被自动装箱)都可以直接被赋给Object类型的变量。enum类型(枚举)预先定义的一组命名值的值类型。使用枚举常量时必须以枚举类型名称为前缀。常量表达式可以用于显式设置枚举常量的值。enumColorSet{Red,Green,Blue}letc:ColorSet=ColorSet.Red;union类型(联合类型)由多个类型组合成的引用类型,包含了变量可能的所有类型。可以将类型为联合类型的变量赋值为任何组成类型的有效值。typeAnimal=Cat|Dog|number;数组类型(Array)由可赋值给数组声明中指定的元素类型的数据组成的对象。数组中第一个元素的索引为0。letnames:string[]=['Alice','Bob','Carol'];void类型用于指定函数没有返回值。此类型只有一个值,同样是void。由于void是引用类型,可用于泛型类型参数。运算符运算符是数据的基本操作,分为赋值运算符、比较运算符、算数运算符、位运算符和逻辑运算符。赋值运算符赋值运算符为=,使用方式如x=y。复合赋值运算符(以op表示)将赋值与运算符组合在一起,其中x\text{op}=y等于x=x\text{op}y。复合赋值运算符列举如下:+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、|=、^=。比较运算符===严格相等,返回true!==严格不相等,返回true==相等,返回true!=不相等,返回true>/>=大于/大于等于</<=小于/小于等于算数运算符一元运算符:-、+、~、!、+++加法-减法*乘法/除法%除法后余数逻辑运算符a&&b逻辑与a||b逻辑或!a逻辑非位运算符位运算符用于对二进制位进行操作,是底层数据处理的重要工具。运算符说明a&b按位与:如果两个操作数的对应位都为1,则将这个位设置为1,否则设置为0a|b按位或:如果两个操作数的相应位中至少有一个为1,则将这个位设置为1,否则设置为0a^b按位异或:如果两个操作数的对应位不同,则将这个位设置为1,否则设置为0~a按位非:反转操作数的位a<<b左移:将a的二进制表示向左移b位a>>b算术右移:将a的二进制表示向右移b位,带符号扩展a>>>b逻辑右移:将a的二进制表示向右移b位,左边补02.3流程控制条件分支语句流程控制可通过条件分支语句和循环语句完成。条件分支语句包括if语句、switch语句和条件表达式。if语句用于需要根据逻辑条件执行不同语句的场景。当逻辑条件为真时,执行对应的一组语句,否则执行另一组语句(如有)。条件表达式可以是任何类型,对于boolean以外的类型会进行隐式类型转换。if(condition){//语句1}elseif(condition2){//语句2}else{//else语句}switch语句执行与switch表达式值匹配的代码块。如果没有任何label值匹配且有default子句,则执行default代码块。break语句(可选)允许跳出switch语句。switch(expression){caselabel1://语句1break;caselabel2:caselabel3://语句23break;default:}条件表达式由condition的布尔值来决定整体表达式的值为expression1或expression2。//condition?expression1:expression2letmessage=Math.random()>0.5?'Valid':'Failed';循环语句循环语句可以实现代码的重复调用,完成复杂的迭代功能。ArkTS提供了for、for-of、while、do-while四种循环语句。for循环for语句会被重复执行,直到循环退出语句值为false。执行流程:①执行init表达式→②计算condition→③执行循环主体→④执行update表达式→⑤回到步骤②。letsum=0;for(leti=0;i<10;i+=2){sum+=i;}for-of循环使用for-of语句可遍历数组或字符串。for(letchof'astringobject'){/*processch*/}while循环只要condition为真值,while语句就会执行statements语句。letn=0;letx=0;while(n<3){n++;x+=n;}do-while循环如果condition的值为真值,那么statements语句会重复执行。与while不同的是,do-while至少执行一次。leti=0;do{i+=1;}while(i<10)2.4函数函数的定义与使用函数是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用,提高开发效率。函数声明与调用函数声明(又称函数定义)引入一个函数,包含其名称、参数列表、返回类型和函数体。函数中定义的变量和其他实例仅可以在函数内部访问,不能从外部访问(作用域)。如果函数中定义的变量与外部作用域中已有实例同名,则函数内的局部变量定义将覆盖外部定义。//函数定义functionjoin(x:string,y:string):string{letz:string=`${x}${y}`;returnz;}//函数的调用letx=join('hello','world');console.log(x);参数列表的格式可选参数格式为name?:Type。当参数有可选参数时,参数的形参可以不给入,函数体中可用undefined进行判断。functionhello(name?:string){if(name==undefined){console.log('Hello!');}else{console.log('Hello,$(name)!');}}Rest参数函数的最后一个参数可以是rest参数,格式为...restArgs。rest参数允许函数接收一个由剩余实参组成的数组,用于处理不定数量的参数输入。functionsum(...numbers:number[]):number{letres=0;for(letnofnumbers)res+=n;returnres;}sum(1,2,3);//返回6箭头函数与函数类型函数可以定义为箭头函数。箭头函数是匿名函数,只有参数列表和函数体。箭头函数定义箭头函数的返回类型可以省略,省略时返回类型通过函数体推断。表达式可以指定为箭头函数,使表达更简短。//完整写法(x:number,y:number):number=>{returnx+y;}//省略返回值类型(x:number,y:number)=>{returnx+y;}//简写表达式(x:number,y:number)=>x+y箭头函数调用箭头函数有两种调用方法://定义时直接调用((x:number,y:number)=>{returnx+y;})(1,2)//用变量存储后调用letsum=(x:number,y:number)=>{returnx+y;};sum(1,2);函数的类型用来表达存储匿名函数变量的类型就是函数类型:letsum:(x:number,y:number)=>number=(x:number,y:number)=>{returnx+y;};sum(1,2);2.5类和接口类和接口类与接口是构建可靠、可扩展程序的两大支柱。类是具体实现蓝图,它封装了数据与行为,用于创建对象实例。而接口则是一种纯粹的类型契约,它定义了对象应有的形状(有哪些属性或方法),但不关心具体实现。类和对象类的定义与实例化类声明引入一个新类型,并定义其字段、方法和构造函数。定义类后,可以使用关键字new创建实例,或者用对象字面量创建对象实例。classPerson{name:string='';surname:string='';constructor(n:string,sn:string){=n;this.surname=sn;}fullName():string{return+''+this.surname;}}letp=newPerson('John','Smith');console.log(p.fullName());类的继承一个类可以继承另一个类(称为基类),并使用extends关键字实现。继承类继承基类的字段和方法,但不继承构造函数。继承类可以新增定义字段和方法,也可以覆盖其基类定义的方法。classEmployeeextendsPerson{salary:number=0;calculateTaxes():number{returnthis.salary*0.42;}}接口接口声明引入新类型。接口是定义代码协定的常见方式。任何一个类的实例只要实现了特定接口,就可以通过该接口实现多态。接口通常包含属性和方法的声明。接口定义方法interfaceStyle{color:string;}interfaceAreaSize{calculateAreaSize():number;someMethod():void;}接口作为数据结构接口常用来代替类以表示一个数据结构:interfacePerson{name:string;age:number;weight:number;}letperson:Person={name:"张三",age:18,weight:100}任务1实施:商品列表查询根据任务描述,利用ArkTS语言构建一个商品数列列表,并打印价格最低的商品信息。遍历查最小创建数组定义接口以下为核心实现代码:interfaceProduct{name:string;price:number;imageSrc:string;}letproducts:Product[]=[{name:'HuaweiMate70',price:5999,imageSrc:'https://...'},//...省略其他商品数据]letcheapProduct:Product={name:'',price:99999,imageSrc:''};for(letproductsElementofproducts){if(productsElement.price<cheapProduct.price){cheapProduct=productsElement;}}console.log('价格最低的手机是:${cheapP},价格为:${cheapProduct.price}');运行后日志打印效果:I价格最低的手机是:HuaweiMate70,价格为:5999任务1思考与拓展💡拓展提升本任务学习使用了ArkTS的基本语法,完成了一个商品列表的数据查询功能。针对查询方法,可以尝试封装成函数进一步提升代码的可维护性。🔍思考感悟通过本任务学习,我们深入理解了ArkTS作为HarmonyOS核心开发语言的设计理念与语法特性。ArkTS在TypeScript生态基础上,通过静态类型检查、对象布局约束等规则,显著提升了代码的健壮性与执行效率。任务2认识组件与页面在APP开发中,界面设计直接影响用户体验。本任务通过创建一个包含文本、按钮和输入框的登录界面,利用组件构建直观的UI。任务将从组件的概念、排布、样式和点击事件几个维度展开。2.6页面ArkUI的基本概念方舟开发框架(ArkUI)为鸿蒙应用的UI开发提供了完整的基础设施底座,包括简洁的UI描述、丰富的UI功能,以及实施界面预览工具,并支持开发者进行可视化的界面开发。UI即用户界面,是用户与应用交互的视觉层。组件UI构建与显示的最小单位,如列表、网格、按钮、单选框、进度条、文本等。ArkUI作为一套开发极简、高性能、支持跨设备的UI开发框架,提供了构建应用UI所必需的能力,主要包括:ArkTS、布局、组件、页面路由与导航、图形、动画、交互事件、自定义能力。移动应用开发框架对比系统开发语言开发框架特点HarmonyOSArkTSArkUI声明式、跨设备AndroidKotlin/JavaJetPackCompose声明式UIiOSSwiftSwiftUI声明式UI第三方DartFlutter跨平台ArkUI框架架构ArkUI框架作为HarmonyOS系统的核心基础设施,其整体架构采用分层设计,从上到下依次为应用层、声明式UI前端、语言运行时、声明式UI后端引擎、渲染引擎、平台适配层和OS。应用层声明式UI前端范式语法基础规范、UI组件/布局/动画、状态管理语言运行时统一字节码、类型系统、AOT、GC机制声明式UI后端引擎基础控件、布局、动效、事件、组件状态管理、内存管理、渲染管线渲染引擎→平台适配层→OS开发范式在HarmonyOS中,ArkUI提供了两种开发范式。ArkUI推荐采用声明式开发范式来构建UI,这种范式可以让开发者以接近自然语义的编程方式描述UI,而无须关注底层绘制和渲染细节,且内存占用更少,性能更优。类Web开发范式也称命令式开发范式,采用经典的HTML、CSS、JavaScript三段式开发方式。该范式更符合Web前端开发者的使用习惯,便于快速将已有的Web应用改造。声明式开发范式(推荐)采用基于TypeScript声明式UI语法扩展而来的ArkTS语言,从组件、动画和状态管理三个维度提供UI绘制能力。将持续增强功能,为开发者提供更丰富、更强大的能力支持。ArkUI声明式语法结构以下展示了一个典型的声明式开发范式结构,点击按钮后文本从"HelloWorld"变为"HelloArkUI"。案例代码的基本组成包括:自定义组件(@Component装饰的struct)、装饰器(@Entry、@Component、@State)、UI描述(build()方法)、系统组件(Column、Text、Divider、Button)、属性方法(fontSize()、width()、height())、事件方法(onClick())。声明式语法核心要素详解1自定义组件简称"组件",是可复用的UI单元,可组合其他组件。使用@Component装饰的struct结构。它是基本的UI元素,用户看到的所有界面UI元素都由这种struct结构组成。2装饰器用于装饰类、结构、方法以及变量,并赋予其装饰对象特殊的含义。@Component表示自定义组件;@Entry约束为入口组件(页面根节点,一个页面有且只能有一个);@State限定状态变量,状态变量变化会触发UI刷新渲染。3UI描述以声明式的方式来描述UI的结构,以build()方法尾随闭包{...}中的代码块来声明描述UI结构。4系统组件ArkUI框架中默认内置的基础和容器组件,可直接被开发者调用,如Column、Text、Divider、Button等。5属性方法与事件方法组件可以通过链式调用配置多项属性(如fontSize()、width()、height()),也可以通过链式调用设置多个事件的响应逻辑(如onClick())。关键区别:组件是被@Component装饰的struct结构;页面则是被@Component和@Entry同时装饰的struct结构。一个页面有且仅能有一个@Entry,只有被@Entry装饰的组件才是页面,才可以调用页面的生命周期。组件的分类与使用组件是构建页面的核心,每个组件通过对数据和方法进行简单封装,实现独立的可视、可交互功能单元。组件之间相互独立,随取随用,也可以在相同需求中重复使用。按提供方式分类系统组件:由ArkUI框架提供,可由开发者直接调用自定义组件:由开发者根据规范自定制,完成数据和UI功能的封装和复用按功能分类(常用系统组件)基础组件:Blank、Button、Checkbox、Divider、Image、Progress、Text、TextArea、TextInput等容器组件:Column、Flex、Grid、List、Row、Scroll、Stack、Swiper、Tabs等媒体组件:Video绘制组件:Circle、Ellipse、Line、Rect、Shape等画布组件:Canvas组件的使用方法在build(){}的尾随闭包中调用相关组件。根据组件构造方法的不同,创建组件分为有参数和无参数两种方式。//Text文本组件的接口定义Text(content?:string|Resource,value?:TextOptions)//组件的调用(不需要new关键词)组件名(参数)自定义组件基本结构@Componentstruct组件名{build(){}}组件使用案例以下展示了文本组件的基本使用,以及多组件使用时的正确与错误方式。例2-1:文本组件使用@Entry@ComponentstructIndex{build(){Text('HelloWorld')}}例2-2:多组件错误案例在@Entry装饰的组件中,build()结构只能拥有一个根组件节点,且必须是一个容器组件。直接放置多个组件会导致编译错误。例2-3:自定义组件设计与调用@Componentstruct组件名{build(){}}@Entry@ComponentstructIndex{build(){组件名()//调用自定义组件}}2.7组件的布局布局基础与容器组件若确有多组件显示的需求,就必然需要使用容器组件。学会使用容器组件及其布局技巧,才能设计出整齐美观的界面。布局技巧01确定页面的布局结构分析整体页面的层次关系和组件嵌套方式。02分析页面中的元素构成确定需要哪些基础组件和容器组件。03选用适合的布局容器使用布局容器组件或属性控制页面中各个元素的位置和大小。常见页面结构根节点(Page)表示页面的根节点,必须声明在build()中,有且仅有一个。组件之间的从属关系称为父子组件关系。支持子组件配置的组件称为容器组件或布局组件。线性容器组件Row与Column线性布局(LinearLayout)是开发中最常用的布局。Column容器内子元素按照垂直方向排列,Row容器内子元素按照水平方向排列。图2-9Column容器内子元素排列示意图图2-10Row容器内子元素排列示意图核心概念主轴布局方向上的轴线。Row主轴为水平方向,Column主轴为垂直方向。交叉轴垂直于主轴方向的轴线。Row交叉轴为垂直方向,Column交叉轴为水平方向。间距通过参数对象的space属性设置排列方向上子元素的间距。例2-4&2-5:容器使用案例//例2-4:Column容器(垂直排列)@Entry@ComponentstructIndex{build(){Column(){Text('HelloWorld')Button('登录')}}}//例2-5:Row容器(水平排列)@Entry@ComponentstructIndex{build(){Row(){Button('登录')Text('HelloWorld')}}}2.8组件的样式属性方法与盒子模型开发者可以通过调整组件的样式以及配置组件的属性方法来实现外观细节的调整,如字体颜色、组件间的距离、边框的厚度或按钮的底色等。属性方法属性方法是组件配套的配置方法,通过方法执行语法完成。属性方法分为通用属性方法(所有组件都具备)和特定属性方法(某个或部分组件才拥有)。如果需要配置多个属性方法,需要以"."链式调用的方式配置。通用属性方法.width(参数)组件宽度.height(参数)组件高度.backgroundColor(参数)组件背景色链式调用示例Text('HelloWorld').fontSize(12).fontColor(Color.Blue).backgroundColor(Color.Pink).width(200).height(50)盒子模型任何组件的规模样式都可以描述为组件的内容(content)、内边距(padding)、边框(border)和外边距(margin)之间的关系。线性布局样式调整线性布局可以参照盒子模型调整布局内容、布局边框的内外边距等。通过space、alignItems、justifyContent等参数或属性调整子组件的间距及水平垂直方向的对齐方式。布局样式示例(例2-8)@Entry@ComponentstructIndex{build(){Column(){Column(){}.backgroundColor(Color.Pink).width(200).height(100).margin({top:20})Column(){}.backgroundColor(Color.Orange).width(250).height(120).margin({top:40})}.backgroundColor(Color.Gray)}}交叉轴对齐方式alignItems属性设置子组件在交叉轴的对齐方式。交叉轴为垂直方向时取值为VerticalAlign类型;交叉轴为水平方向时取值为HorizontalAlign类型。主轴对齐方式justifyContent属性设置子组件在主轴上的对齐方式,取值为FlexAlign类型:Start、Center、End、SpaceBetween、SpaceAround、SpaceEvenly。2.9组件的点击事件组件的点击事件应用界面不仅提供华丽的UI界面,一般也提供用户交互的逻辑。事件处理是用户与应用程序交互的核心机制,系统组件通过事件响应用户操作,如点击、滑动、长按等。事件处理是通过组件的事件方法来配置,以"."链式调用的方式配置。事件的配置事件的配置需要在事件方法的参数中传入箭头函数。使用箭头函数表达式配置组件的事件方法,要求使用()=>{...},以确保函数与组件绑定,同时符合ArkTS语法规范。Button('Clickme').onClick(()=>{console.log('您点击了按钮');})this的作用域箭头函数内部的this是词法作用域,由上下文确定。匿名函数可能会有this指向不明确问题,在ArkTS中不允许使用。ArkTS语法不推荐使用成员函数配合bindthis去配置组件的事件方法。任务2实施:简易登录页面根据任务描述,创建一个包含文本、按钮和输入框的登录界面。配置事件调整样式选择组件布局规划核心代码@Entry@ComponentstructIndex{build(){Column(){Text("登录")TextInput()TextInput()Button("点击登录").width(200).margin({top:20}).onClick(()=>{console.log('您点击登录');})}}}运行效果图2-16简易登录页面图2-17点击按钮事件日志任务3基于状态管理实现动态应用应用的界面通常不是一成不变的,而是根据用户的交互发生变化。本任务将设计一个页面浏览点赞的功能,要求点击点赞组件后,点赞计数组件颜色变红且点赞计数量显示加1。如果希望构建一个动态的、有交互的界面,就需要引入"状态"的概念,以便高效地完成数据与UI的绑定与共享。2.10状态管理基础状态与UI的关系在ArkUI框架中,开发者只要更新UI所绑定的状态,系统就会以响应式的处理方式自动更新渲染界面,无需手动查找组件对象并设置内容。View(UI)UI渲染,指将build方法内的UI描述和@Builder装饰的方法内的UI描述映射到界面。State(状态)指驱动UI更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。UI最终的效果由参数状态所决定,若参数发生变化,UI也应该发生相应地变化。这种由应用运行时状态变化引发的UI重新渲染,在ArkUI中统称为状态管理机制。状态管理核心概念以下通过一个示例来解析状态管理的核心概念:@ComponentstructMyComponent{@Statecount:number=0;//状态变量privateincreaseBy:number=1;//普通变量build(){}}@Entry@ComponentstructParent{build(){Column(){MyComponent({count:1,increaseBy:2})}}}1状态变量被状态装饰器装饰的变量,值的改变会引起UI的渲染更新。示例:@Statecount:number=0。2常规变量没有被状态装饰器装饰的变量,通常应用于辅助计算。它的改变永远不会引起UI的刷新。示例:increaseBy。3数据源/同步源状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。4命名参数机制父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段。示例:MyComponent({count:1,increaseBy:2})。@State装饰器的用法被@State装饰器装饰的变量称为状态变量。当状态变量作为参数提供给ArkUI组件时,就完成了"绑定",状态变量的数据变化会引起组件UI的重新渲染。①定义变量并初始化定义UI参数对应的变量,并完成初始化。②添加@State装饰器给该变量添加装饰器@State。③绑定给UI组件将创建好的状态变量绑定给UI组件。④修改状态变量修改状态变量,UI重新渲染,绑定效果更新。@Entry@ComponentstructIndex{@Statemsg:string='HelloWorld';build(){Column({space:20}){Text(this.msg).fontSize(30)Button('点击按钮改变文本内容').onClick(()=>{this.msg='HelloArkUI'})}}}@Watch与$$运算符除了基本的@State装饰器,ArkTS还提供了@Watch和$$运算符等特性来为开发者提供更多功能。@Watch装饰器用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。@Watch仅能监听到可以观察到的变化,使用严格相等(===)判断数值有无更新。使用步骤:①需要有一个监听目标(状态变量)②添加@Watch装饰器,参数中提供回调方法名③构建回调方法,设计状态变化后的执行动作@Watch('heartRateCallback')@StateheartRate:number=75;heartRateCallback(){if(this.heartRate>100){console.log('告警,您的心率过快:'+this.heartRate);}}$$运算符给内置组件提供变量的引用,使得变量和内置组件的内部状态保持同步。如果说@State装饰的状态变量能够完成数据变化到UI的自动更新,则$$运算符能够完成数据和UI的双向绑定。一个典型的例子是TextInput组件的使用:@Entry@ComponentstructIndex{@StatetextShow:string='';build(){Column({space:20}){Text(this.textShow).fontSize(40)TextInput({text:$$this.textShow}).width('80%')}}}2.11组件级和应用级状态管理状态管理的层级根据状态变量的影响范围,状态管理可以大致分为组件级状态管理和应用级状态管理。@State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。数值改变时引起相关组件的渲染刷新。@Prop装饰的变量可以和父组件建立单向同步关系。@Prop装饰的变量是可变的,但修改不会同步回父组件。@Link装饰的变量可以和父组件建立双向同步关系,子组件中@Link装饰变量的修改会同步给父组件。@Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias或属性名绑定。应用级状态管理如果开发者要实现应用级的、或者多个页面的状态数据共享,就需要用到应用级别的状态管理。ArkTS根据不同特性,提供了多种应用状态管理的能力:LocalStorage页面级UI状态存储,通常用于UIAbility内、页面间的状态共享。是内存级别的存储方式。使用步骤:①定义LocalStorage输入存储数据(key-value形式)→②绑定到@Entry装饰器参数中→③组件通过@LocalStorageProp或@LocalStorageLink获取数据。AppStorage特殊的单例LocalStorage对象,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。PersistentStorage持久化存储UI状态,通常和AppStorage配合使用,选择AppStorage存储的数据写入磁盘,以确保属性在应用程序重新启动时的值与关闭时相同。Environment应用程序运行的设备的环境参数,这些参数会同步到AppStorage中,可以和AppStorage搭配使用。任务3实施:点赞功能任务的UI设计效果为一个华为Mate70Pro+的宣传卡片,包含主题图片、Logo、文字和点赞区域。图2-23任务目标效果核心实现代码@Entry@ComponentstructIndex{@StatelikeCount:number=8888;likeState:boolean=false;build(){Column({space:10}){...Row(){Image($r('app.media.ic_love')).width(20)Text(this.likeCount.toString())}.onClick(()=>{if(this.likeState===false){this.likeCount++;this.likeState=true;}else{this.likeCount--;this.likeState=false;}})}}}任务3运行效果与思考在点赞区域点击,界面显示的数据会加1;再次点击后,数据会退回原始状态。💡拓展提升实际应用中点赞功能一般都伴随点赞区域颜色的变化。可以通过对点赞区域的图片和文本组件设置颜色的状态变量来完成。🔍思考感悟本次任务体现了状态管理在动态应用开发中的重要性。ArkUI框架通过状态装饰器(如@State、@Prop等)简化了数据与UI的绑定,使得开发者能够更高效地实现交互功能。任务4动态应用中的渲染控制某些应用中UI模块的显示是变化的,不同的情况显示不同的形态。本任务将设计一个商品浏览页面,要求有图文并茂的商品数据、价格和折扣情况。如果要动态地控制和显示组件,并且能够根据打折情况显示折扣内容,就必须了解UI的渲染控制。2.12条件渲染条件渲染ArkTS提供了渲染控制的能力,条件渲染可根据应用的不同状态,使用if、else和elseif渲染对应状态下的UI内容。基于条件语句进行判断,并在判断结果中书写声明UI内容,条件满足则UI语句生效。使用规则支持if、else和elseif语句条件语句可以使用状态变量(值的改变可以实时渲染UI)或常规变量允许在容器组件内使用,通过条件渲染语句构建不同的子组件更新步骤当if/elseif后跟随的状态判断中使用的状态变量值变化时:①评估条件,如果分支没有变化则无须执行后续步骤→②删除此前构建的所有子组件→③执行新分支的构造函数,将获取到的组件添加到if父容器中。条件渲染案例:商品库存采用加减两个按钮来模拟商品销售和补货情况。当商品库存数量为0时,"库存告急!"的文本则显示出来。@Entry@ComponentstructIndex{@Statecount:number=1;build(){Column({space:10}){Row({space:10}){Button('−').onClick(()=>{if(this.count>0){this.count--;}})Text(this.count.toString())Button('+').onClick(()=>{this.count++;})}if(this.count<=0){Text('库存告急!')}}}}如果库存状态变量count从1减少到0,条件count\leq0将从false更改为true,因此执行条件为真分支的构造函数,创建Text组件并添加到父组件Column中。2.13循环渲染ForEach循环渲染循环渲染通过ForEach接口来完成。ForEach接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用。ForEach接口参数说明参数名类型必填说明arrArray是数据源,为Array类型的数组itemGenerator(item,index)=>void是组件生成函数,为数组中的每个元素创建对应的组件keyGenerator(item,index)=>string否键值生成函数,为数据源的每个数组项生成唯一且持久的键值实现步骤01构建数据源数据源是数组,数组的类型可以使用ArkTS基础类型或对象类型。02书写ForEach接口将数据源数组传入给参数1。03实现组件生成函数参数2的匿名函数会被循环迭代,迭代次数就是数组的规模。ForEach使用案例:新闻列表interfaceArticle{title:string;createTime:string;}@Entry@ComponentstructIndex{@Statearticles:Article[]=[{title:'华为即将推出Mate70系列手机',createTime:'2024-11-01'},...];build(){Column({space:25}){Button("模拟添加新闻").onClick(()=>{this.articles.push({title:'华为即将推出Pura80系列手机',createTime:'2025-01-01'})})ForEach(this.articles,(item:Article,index:number)=>{Column({space:5}){Text(item.title).fontWeight(FontWeight.Bold).fontSize(20)Text(item.createTime).fontColor('#c4c4c4')}.alignItems(HorizontalAlign.Start)})}}}任务4实施:商品浏览页面设计一个商品展示列表页面,每一个商品项包括商品图片、商品名文字、价格文本,以及在特殊折扣情况下的折扣信息。通过ForEach循环渲染呈现商品列表,通过if/else条件渲染配置折扣商品的展示。数据结构与循环渲染interfaceItem{name:stringimage:ResourceStrprice:numberdiscount?:number}//循环渲染商品列表ForEach(this.items,(item:Item)=>{Row({space:10}){Image(item.image).width(100)Column({space:4}){Text()Text('¥'+item.price)}}.height(120)})条件渲染折扣信息if(item.discount){Text('原价:¥'+item.price).fontColor('#CCC').fontSize(14).decoration({type:TextDecorationType.LineThrough})Text('折扣价:¥'+(item.price-item.discount)).fontColor('#F36').fontSize(18)Text('补贴:¥'+item.discount).fontColor('#F36').fontSize(18)}else{Text('¥'+item.price).fontColor('#F36').fontSize(18)}任务5组件封装与复用随着页面复杂度的提高,代码量也会同步增长。一段臃肿的代码是不容易阅读和维护的。本任务基于上一小节的商品列表,丰富了部分页面内容,并针对代码进行优化和封装,以达到高效、简洁、规范的设计模式要求。2.14封装与复用@Extend拓展组件@Extend装饰器用于扩展原生组件样式,可以对指定组件的私有属性、私有事件和自身定义的全局方法进行封装和重用。基本语法//1.定义组件扩展@Extend(目标组件)function扩展方法名(方法参数){.目标组件支持的样式或事件()...}//2.调用扩展方法目标组件().扩展方法名()使用规则@Extend支持封装指定组件的私有属性、私有事件和全局方法装饰的方法支持参数(基础类型、数组、对象、function)参数可以为状态变量,状态变量改变时UI正常刷新仅支持在全局定义,不支持在组件内部定义只能在当前文件内使用,不支持导出对某一组件进行扩展,其方法只能用在同一组件上优化冗余代码示例@Extend(Text)functiontextExtend(color:ResourceColor,txt:string){.textAlign(TextAlign.Center).backgroundColor(color).fontColor(Color.White).fontSize(30).onClick(()=>{console.log('文本'+txt)})}//使用:代码变得简洁Text('Fancy1').textExtend(Color.Red,'1')Text('Fancy2').textExtend(Color.Orange,'2')@Styles通用样式复用@Extend只能针对某一组件进行扩展和复用。针对组件公共的通用样式,ArkTS推出了可以提炼公共样式进行复用的装饰器@Styles。使用规则仅支持通用属性和通用事件(如width、height、backgroundColor、onClick等)可以定义在组件内或全局(全局需加function关键字)组件内定义的@Styles可以通过this访问组件的常量和状态变量组件内@Styles的优先级高于全局@Styles限制条件@Styles方法不能有参数,否则编译期会报错不支持在@Styles方法内使用逻辑组件//全局定义@StylesfunctionglobalFancy(){.width('100%').height('100%').backgroundColor('#EFEFEF')}//组件内定义@ComponentstructFancyUse{@StateheightValue:number=100;@Stylesfancy(){.height(this.heightValue).backgroundColor(Color.Yellow).onClick(()=>{this.heightValue=200;})}}@Builder自定义构建函数@Extend和@Styles都只能支持样式和事件的封装与复用,但如果涉及组件的结构或布局,则可以考虑使用@Builder自定义构建函数来实现。@Builder装饰器有两种使用方式:组件内私有和全局。组件内私有构建函数@Entry@ComponentstructIndex{@Builder构建函数方法名1(){//布局与组件}@Builder构建函数方法名2(参数列表){//布局与组件}build(){Column(){this.构建函数方法名1()this.构建函数方法名2(参数列表)}}}全局自定义构建函数@Builderfunction构建函数方法名(){//布局与组件}@Entry@ComponentstructIndex{build(){Column(){构建函数方法名()}}}使用限制不涉及组件状态变化时,建议使用全局构建方法@Builder内部不允许修改参数值通过按引用传递参数才会触发动态渲染UI,且参数只能是一个参数必须按照对象字面量的形式传入2.15组件的自定义封装自定义组件详解和@Builder装饰器的能力类似,自定义组件同样可以针对组件的样式、事件和布局结构进行封装复用。但自定义组件内部可以拥有组件变量和组件方法,能够实现更为复杂功能的封装。自定义组件的基本结构1struct自定义组件基于struct实现,"struct+自定义组件名+{...}"的组合构成自定义组件,不能有继承关系。实例化可以省略new。组件名不能和系统组件名相同。2@Component仅能装饰struct关键字声明的数据结构。被装饰后具备组件化的能力,需要实现build方法描述UI。一个struct只能被一个@Component装饰。3build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。4@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。其build()函数下的根节点必须为容器组件。5参数传递自定义组件在调用时,其参数传递以对象的形式传入给组件的成员变量。任务5实施:代码优化封装基于商品列表页面,通过@Extend、@Styles、@Builder和自定义组件对代码进行优化和封装。自定义组件:顶部导航栏@ComponentstructHeader{privatetitle:ResourceStr='默认标题'build(){Row({space:5}){Image($r('app.media.ic_public_back')).width(30)Text(this.title).fontSize(28).fontWeight(FontWeight.Bold)Blank()Image($r('app.media.ic_public_refresh')).width(30)}}}@Extend:价格文本样式@Extend(Text)functionpriceText()
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 北师大版小学数学二年级上册《谁的得分高》说课稿
- 八年级英语上册Unit 6 单元整体教学设计
- 八年级数学上册《三角形》单元复习课教案
- 北师大版初中数学九年级上册平行线分线段成比例定理教学设计
- 本科人力资源管理专业《人才测评模型》单元教学设计
- 第四节 地表形态的变化教学设计高中地理湘教版选修Ⅰ宇宙与地球-湘教版2004
- 2025-2026学年阅读春教学设计
- Dining with Dragons (教学设计)丽声北极星分级绘本四年级上(江苏版)
- 2026年特种设备检验人员资格考试(压力管道检验师GDS)历年参考题库含答案
- 生产管理员培训知识试题(附答案)
- 大学语文(第三版)教案 沁园春·叠嶂西驰(教案1)
- 电话邀约话术及技巧
- 新视野大学英语(第四版)读写教程4(思政智慧版)课件 Unit 3 Business success in the new age Section A
- 老年人能力评估师第一章-评估准备
- 2023年广州番禺区小升初六年级英语期末试卷及答案(含听力原文)
- 绿色食品生产记录表黄瓜
- 消化系统常见肿瘤(临床病理)
- 铁路货车运用维修规程(2021版)
- “减负、增效、提质”理念下基于学科核心素养的小学英语作业设计优化策略研究 论文
- GB/T 26480-2011阀门的检验和试验
- GB/T 13277.3-2015压缩空气第3部分:湿度测量方法
评论
0/150
提交评论