HarmonyOS 鸿蒙Next【小白学鸿蒙-学习笔记】关于鸿蒙的一点吐槽与近期学习的体会
HarmonyOS 鸿蒙Next【小白学鸿蒙-学习笔记】关于鸿蒙的一点吐槽与近期学习的体会
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
关于HarmonyOS 鸿蒙Next【小白学鸿蒙-学习笔记】关于鸿蒙的一点吐槽与近期学习的体会的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。
<markdown _ngcontent-lku-c237="" class="markdownPreContainer">
前言
学习HarmonyOS也有一段时间了,发现了一些问题,也有一些体会,写在这里, 也是对自己近期的一个学习体会的总结。因为我之前是学Java的,没有安卓的相关开发经验,只有玩过一段时间的微信小程序,所以以下内容,如有错误,敬请指正。
吐槽
学习HarmonyOS最大的一个问题就是目前手头上没有合适的华为手机,借了一个Nova5Pro,结果当时不能升级到3.0系统,后面升级到了3.0系统之后,API版本还是6,导致一直都没有真机做测试,使用模拟器和预览器也勉强够用,不过学习过程中也有遇到一些Bug,后面再说
第二个问题就是HarmonyOS的版本跟API的版本,个人感觉有点混乱,因为你手上拿着一个设备,你是完全不知道它支持的API版本是多少,此处强烈建议华为的人想办法解决一下这个问题,有一个最简单的方式就是直接把API版本写在手机的开发者模式,这样进去就知道当前手机的API版本,这样不是比较简单吗?
感觉官方文档对于初学者来说并不是很友好,学习路线并不线性,官方文档表示,后期鸿蒙开发的主力肯定是ArkaTS+Storg模型,所以我选择直接先从API8入手,学习ArkTS,但是发现,对于ArkTS的学习,我个人之前只学过JS,对于TS的语法很多时候看到的时候一脸懵逼,但是官方文档对于这块内容好像默认你都会似的,也没写,只能自己去查,去摸索,增加了我的学习成本。
CodeLabs的形式非常好,有用的内容也不少,但是一开始,我随便打开一个CodeLabs也是一脸懵逼的,为什么这么多文件,为什么这么多引用,对于初学者而言,不是应该简单点好理解一些比较好吗,但是CodeLabs目前的形式,个人感觉有点吓到我,并且对于CodeLabs的引导,给我一种,“我们来学习,这是1,这是2,这是3,1+1=2,1+2=3,你学会了吗?好了现在我们来造航母吧!”我个人感觉非常难受。不知道其他人会不会跟我有同样感觉。
吐槽就先吐槽到这里,接下来对目前学习的一个内容进行一个总结。
知识总结
对于这块内容,我是站在一个新手的角度得出的内容,如有不对的内容,请指正
入门:
基础:
了解:
熟悉:
重要
- 完成快速入门的案例编写,以此体会创建项目、目录结构、配置文件及装饰器、组件等相关概念
- API8页面跳转案例
- API9页面跳转案例
TS通用语法
类型
变量声明
name:type = value
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
联合类型
- 打个比方说image的src属性,传进去的参数可以是字符串也可以传一个资源路径,为什么可以这样呢?点进去看一下,他是这么写的:
src: string | PixelMap | Resource
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
- 在类型定义的时候,是用了"|",意思是可以是这个类型,也可以是另一个类型
数组类型
- 最基础的很简单:
let numberArray: number[] = [1, 2, 3] // var numberArray = [1, 2, 3];
let numberArray1: Array<number> = [4, 5, 6] // var numberArray1 = [4, 5, 6];
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
- 联合类型也可以用数组:
let arr: (string | number)[] = [1, 'a']
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
- 复杂对象也可以用数组:
let arr: {name: string, age: number}[] = [
{name: 'Jane', age: 17},
{name: 'Jian', age: 20}
]
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
元组
元组算是一个新东西,Python也有用到,本质上就是一个确定数量和类型的数组
类型和位置需要一一对应
let data: [number, string, boolean] = [2, '3', true] // var data = [2, '3', true];
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
枚举
- 这个也是使用enum枚举关键字,可以为枚举项赋值,不赋值默认从0开始,赋值后,这个值就是该枚举中枚举项的下标
enum Direction {
Up = 1, // 不赋值默认从0开始
Down,
Left,
Right
}
console.log(Direction.Down) // 2
console.log(Direction[1]) // Up
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
类型断言
- 逻辑类似于Java的类型强转,有两种实现方式
str as string
<string>str //这两种方式都是将变量str,强制变成string类型
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
类型别名
- 使用type关键字可以给某一个Object对象起一个临时性的别名
type Lady = {name: string, age: number} // 对象类型可以使用类型别名
let arr: Lady[] = [
{name: 'Jane', age: 17},
{name: 'Jian', age: 20}
]
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
接口
接口提供一种数据结构的抽象定义,跟Java的会有所区别,不仅有方法的定义也有属性的定义,定义完了他就是一种数据结构
interface MyInterface {
name: string,
age: number,
say(): string
}
function fn(opts: MyInterface) {
//…
}
fn({
name:“张三”,
age:18,
say(){
return “哈哈哈”
}
})
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
接口的实现与继承
- 跟Java一样,类使用implement关键字实现接口,实现接口后需要实现接口中的方法
- 可以实现多个接口
- 接口之间可以继承,A接口可以继承B接口和C接口,使用Extends关键字
类
属性声明
- 跟Java有所区别,属性默认是Public的
- Public在所有地方都可以访问
- protectd受保护,在类内部和其子类中能够访问,实例中不能访问
- private:私有,只能在内部访问。
- readonly:只读,实例不能对这个属性赋值
构造函数关键字
- 在类中,使用constructor关键字声明构造函数
静态成员
- 跟Java一样,使用Static关键字修饰,修饰后无法使用this访问,必须使用类名调用和修改
存取器
- 使用get\set修饰属性的同名函数,给私有属性一个存取方式,在存的时候可以设定一定的规则,不符合规则的不存
抽象类
- 跟Java一样,抽象类不能用来创建对象,只是专门用来被继承的
- 抽象类中可以有抽象方法和实例方法,抽象方法必须被子类实现,实例方法子类的实例对象可以直接调用
函数
函数类型
在TS中,函数有两种类型,一种是函数声明,其实就是先定义函数,然后用到的时候,使用函数名调用
另一种类似于Java的匿名函数,用到的时候直接使用function关键字创建一个函数
函数的返回值跟属性的返回值一样,需要使用“:返回类型”
//函数声明
function sum(x: number, y: string): string {
return x + y
}
//函数表达式 这种情况,sum的类型是ts自动推断得出的string类型
let sum = function (x: number, y: string): string {
return x + y
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
- 函数也可以成为属性的一种类型
let sum:(x:number,y:string)=>string
//属性sum为一个函数,函数形参为(x:number,y:string),返回值为string
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
- 函数表达式也可以简化成为箭头函数
(形参)=>{
运算逻辑
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
可选参数
当在组件或者函数中,某些参数可传可不传,就可以用到可选参数,使用方式如下,
注意,如果一个函数中同时有必选参数和可选参数,可选参数一定要在后面
add(num?:number){
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
默认参数
- 当使用上面的写法的时候,num是没有默认值的,如果我们在函数内有用到该参数,这样就可能会报错,这个时候可以使用默认值的方式,这样参数也是可以省略的,如果省略就会使用默认值
add(num:number=3){
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
剩余参数
- 在Java中,这个叫可变参数,在指定函数的参数个数时,可能无法确定,那么可以将最后一个参数封装成为一个集合,然后在集合中遍历取出参数
function sum(x: number, ...rest: string[]): string[] {
return rest.map(i => i + x)
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
函数重载
- 在Java中也是有方法重载,同名的方法,根据传参的内容不同调用不同的方法,但是在Ts中,函数的每一个形参可以指定不同的参数类型,那么可以在函数内部进行参数判定,但是这种会比较麻烦,所以能用重载也可以用重载
function fn(x: number, y: number): number
function fn(x: string, y: string): string
function fn(x: string|number, y: string|number): string|number{
if(typeof x === 'number' && typeof y === 'number') {
return x + y
} else if(typeof x === 'string' && typeof y === 'string') {
return x + '_' + y
} else {
return '错误'
}
}
// 如果没有前两个重载这里不会报错,输出内容是“错误”
// 如果有了前两个重载这里就会报错,因为此时的参数不符合重载函数的任何一种传参数据类型
fn(10, ‘kkk’)
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
泛型
泛型函数
- 泛型函数跟Java一样,可以让函数的参数类型在使用时决定。
泛型接口
- 泛型接口跟泛型函数差不多
泛型类
- 其实跟Java也差不多
TS中的This
- 如果在箭头函数中,this指向的是当前组件,
- 但是在如果使用匿名函数的方式,需要在事件后.bind(this)
ArkTS语法
UI描述
UI组件
无参数构造组件
有参数构造组件
组件名(参数){
子组件
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
属性方法
- 通过链式调用的方式
- 参数可以传正常的参数外,可以使用枚举类型,具体的可以按进去,看需要传入什么参数
事件方法
- 为当前组件绑定事件,当事件发生时可以进行响应
- 使用方式有三种,一般建议使用前两种
- 直接写箭头函数,
- 把函数定义在外面,然后通过This.functionName调用(不用加括号)
- 使用匿名函数,但是当函数体里面用到this关键字时,需要.bind(this),这个this指向当前组件
子组件配置
- 当一个组件可以包含子组件时,子组件需要写在{ }里面
- 子组件也可以嵌套其他的子组件
装饰器
带@ 就是装饰器,如[@State](/user/State)、[@Entry](/user/Entry)
组件定义装饰器
[@Component](/user/Component)
- 简单理解,被修饰后,这就是一个组件了,可以复用
- 如果想给其他页面复用,需要使用export关键字,然后对应页面使用 import关键字即可导入使用
[@Entry](/user/Entry)
- 如果你想让一个组件单独以一个页面展示,那就需要用到这个修饰器,没什么好说的
- 切记:是一个页面一个,我当时傻傻的以为入口嘛应该就一个,三个页面就index页面加了这个,结果毫无疑问的报错了
[@Rreview](/user/Rreview)
- 学会用预览器之后就会发现,使用预览器还是挺爽的,但是预览器只能预览页面,也就是有加[@Entry](/user/Entry)的组件,如果我想预览自定义组件怎么办呢?这就需要用到[@Preview](/user/Preview)了,给自定义组件加上这个,就可以以组件的形式去预览了,所见即所得,还是挺爽的。
动态构建装饰器
[@Builder](/user/Builder)
- 这个装饰器可以修饰一个函数,函数内部定义一个组件,可以达到复用的目的
- 在定义动态组件的时候,可以声明一些参数,然后在组件内部使用它,这样当动态组件被使用的时候,可以传参进去,就达到动态复用的目的
[@Styles](/user/Styles)
- 这个装饰器是用来降低重复的样式代码,不过它里面只能声明一些通用属性,不能声明组件特有的样式。
- 并且两种使用方式:要么就在builder函数之前,要么就在当前组件之外,这样要加一个Function关键字
[@Extend](/user/Extend)
- 如果你需要用到很多个Text组件,然后又不得不为他们定义相同的样式的时候,可以试试[@Extend](/user/Extend)关键字,它可以给基础组件快速扩展同一类样式。
- 这个装饰器只能声明在当前组件的外面,并且也要Function关键字
[@CustonDialog](/user/CustonDialog)
- 使用这个注解可以让你声明一个弹出框,并在想要的时候展示他
- 步骤大概是,
- 创建一个弹窗组件
- 然后在父组件中创建对应的控制器,然后在控制器的构造函数中传入此弹窗组件及其他参数
- 为当前页面的某一个组件绑定事件,当事件触发时,执行弹窗控制器的open方法
- 具体的使用方式参照可以点击这里
状态管理装饰器
[@State](/user/State)
- 这个装饰器用来修饰组件内部的变量,当该变量发生变化时,页面上应用该变量的内容会重新刷新
- 这个只是单向绑定,修改值时并不会自动修改变量,所以需要绑定事件,在事件里修改变量,比如当这个值绑定一个输入框的时候,输入框中值的变化不会同步到该变量上,需要手动去修改
- 在声明时要给定初始值
[@Prop](/user/Prop)
- 这个装饰器修饰的变量声明在子组件中,但是初始化由父组件完成,父组件创建该子组件时,需要使用父组件的[@State](/user/State)变量去初始化它
- 也可以理解为父组件的[@State](/user/State)变量绑定到了子组件的[@Prop](/user/Prop)变量上,当父组件的[@State](/user/State)变量发生变化时,使用到该[@Prop](/user/Prop)变量的组件也会发生变化,但是反过来就不会
- 简单来说就是声明一个需要父组件传递过来的变量,谁用到我这个组件,谁就要给我传这个变量
[@Link](/user/Link)
这个装饰器算是增强版的[@Prop](/user/Prop),因为它可以让父组件中的[@State](/user/State)变量跟子组件中[@Link](/user/Link)修饰的变量联动起来,当任一一方对变量进行修改时,会同步到另一方。
值类型必须相同,不能在组件内部初始化,必须接收父组件的[@State](/user/State)变量初始化
使用时需要使用$关键字,
子组件变量:$父组件变量
如text:$text
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
[@Watch](/user/Watch)
这个装饰器用来监视某一个状态变量的变化,当发生变化时,就会调用该装饰器注册的函数
使用方式为:
// [@State](/user/State) [@Watch](/user/Watch)("函数名") 变量名:变量类型= 初始值
@State @Watch(“add”) num:number = 0
//当num每一次发生变化时,就执行一次Add函数
add(){
this.xxx+=1
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
[@Consume](/user/Consume)和[@Provide](/user/Provide)
[@Provide](/user/Provide)为数据的提供方,可以讲数据同步给其他被[@Consume](/user/Consume)修饰的变量,但是前提是,变量名需要一样
[@Consume](/user/Consume)为数据的接收方,本身不可以自行初始化变量,当感知到[@Provide](/user/Provide)数据的更新时,会触发当前组件的重新渲染。
在使用[@Provide](/user/Provide)和[@Consume](/user/Consume)时,要避免循环引用导致死循环。
渲染控制
if/else
- 这是很好理解的吧,为true就渲染该组件,为False就执行Else里面的组件
ForEach
- 这个也很好理解,特别适合于那种样式一样只有内容不一样的组件内容填充
- 使用需要三个东西,遍历的集合,渲染子组件的方法,生成Key值的方法
LazyForEach
- 数据懒加载,使用这个它不会一下子把所有的加载出来,而是按需加载和创建
组件
容器组件
Flex
- 弹性盒容器组件,默认是水平的主轴,跟垂直的交叉轴,也就是说是横向排列的
- 可以设定FlexDirection,改变主轴的方向,变为列排列之类的等等
- 也可以设定justifyContent,是主轴的对齐方式方式
- 也可以设定AlignItems,设定交叉轴的对齐方式
- 具体的可以看文档
Row
- 行组件,容器内元素以行排列,也没啥好说的
- 列默认的宽度是100%,横向占满一行
- RowSplit:每个子组件加一道分割线
Column
- 列组件,容器内元素以列排列,更没啥好说的
- 列默认的高度是100%,纵向占满一列
- ColumnSplit :每个子组件之间加一道分割线
List
- 列表组件,常用于搭配ForEach实现统一类型元素的渲染
- 内含ListItem
Tabs
- 导航组件,内含TabContent作为页签,每一个页签对应着一个内容视图
Navigator
- 路由容器组件,常用来套在某一个元素外面,为这个元素添加一个跳转效果,当该元素被点击时就执行跳转
Stack
- 堆叠容器,就是栈的排列方式,先放进去的在最底下,然后一层一层铺上去
- 相对布局组件,但是从API9才开始支持,API8不能用
- 可以设置容器内组件相对于其他容器,或者相对于父容器的位置,相对来说比较自由,但是也比较繁琐的一个布局
Swiper
- 滑动轮播组件,可以滑动,也可以轮播
GirdRow
- 栅格容器组件,搭配GridCol使用,
- 可以理解为把屏幕按比例分成若干个栅格,布局按栅格划分,在不同的屏幕尺寸上,栅格大小是不同的,所以占用屏幕尺寸也是会等比例缩小或者放大,从而实现屏幕大小的自适应
- 网格容器,由行和列分割的单元格组成,由GridItem占用格的大小,来展现布局
- 可以理解为一种可滑动的弹出框,可以用作应用内通知栏
- 可以滚动的容器组件,当子组件布局尺寸超过父组件时,可以滚动
- 侧边栏组件,传入的第一个组件为侧边栏,就是展开的时候会显示出来的东西,第二个组件是主页面组件
- 下拉刷新动效,具体可以看文档
- 标识组件,就是类似于微信的未读提醒
Counter
- 计数器组件,在值的两侧有一个加减符号,可以分别设定回调函数,以实现加减功能
- 可以加一个input组件,实现可以加减,也可以输入的功能
- 目前有个Bug,当含有子组件时,设置子组件的margin属性,此时子组件就消失了
AlphabetIndexer
- 字母索引条,一般用在通讯录应用啥的,
基础组件
Button
- 按钮组件,具体看文档
Image
- 图片组件,具体看文档
Text
- 文本组件,具体看文档
- 可以添加Span组件,用于给文本做一定装饰
TextInput
- 文本输入框组件,具体看文档
Blank
- 这个组件一定程度可以让我们的布局设计更简单,因为它是默认占据剩余的空白空间
- 仅当父组件为Row/Column时生效,当父组件不设置宽度时,Blank失效,所以可以设置个最小宽度
Divder
- 分割器组件
LoadingProgress
- 加载动效的组件,具体看文档
Radio
- 单选框组件,没啥说的,看文档
CheckBox与CheckboxGroup
- 多选框组件,与全选,看文档
- 有一点需要特别注意,当有用到CheckboxGroup时,该组件必须在最上面
Toogle
- 勾选框样式、状态按钮样式、开关样式
- 在使用时需要指定样式与默认状态
DataPanel
- 数据面板组件,有线形跟环形两种样式,用于体现数据占比
滑动选择器
- DatePicker:日期选择器
- TextPicker:文本选择器
- TimePicker:时间选择器
- 这些选择器可以搭配Panel组件或者弹窗组件来进行弹出选择
Marquee
- 跑马灯组件,当文本内容宽度超出组件宽度时,实现跑马灯样式的滚动效果
Navigation
- 页面的根组件,可以用来设置页面的标题、工具栏、菜单等内容
TextClock
- 将当前时间以文本形式展示
- 文本计时器组件,可以正计时,倒计时、
- 控制器可以开始、暂停、重置
下拉选择菜单
- Select:给定一个数组,返回选择的数组下标
评分条
- Rating:可用于电影评分之类的场景
滑动条
- Slider:可用于滑动调节值
进度条
- Progress:各种样式的进度条组件
二维码
- QRCode:可以将Value转化成二维码图片进行展示
搜索框
- Search:没啥说的
分割器
- Divider:提供一个分割条的样式,仅此而已
图表
- Gauge:构建 一个环形图表,然后有一个指针指向当前数据所在的位置,可以理解为汽车上的速度指示器那种样式
媒体组件
Video
- 视频播放组件,这个需要用到的时候,再去看吧
弹窗
警告弹窗:AlertDialog
- 其他的弹窗也都差不多,可以看文档
资源的使用
- 在开发过程中,肯定需要用到很多的资源,比如定义好的字符串、图片音频等,这些资源文件统一放在Resources目录下
- 使用方式1:$r("app.type.name") 此方式可以调用base目录下的资源,切记,此方式下,不支持字符串拼接
- 使用方式2:$rawfile("filename") 此方式直接使用rawfile目录下的文件(一般使用的是图片文件),并且需要包含文件后缀,此方式可以进行字符串拼接
- 其他可以看文档
测验
完成以上内容的学习时,可以尝试完成测试
功能模块:
@ohos.router (页面路由)
- router.push:跳转到指定页面
- router.replace:使用页面替换当前页面,当前页面会被销毁
- router.back:返回到上一页,或返回到指定页面
- 可以传入一个参数:RouterOptions,该参数用于指定路由参数:跳转页面的url和传递的参数Params
- router.getParams:在跳转后的页面中获取传入的参数,此参数为Object类型,需要使用router.getParams()['key']来获取对应的值
进阶
自定义组件的生命周期
aboutToAppear
- 创建实例之后,build函数之前执行,可以在这里做一些数据的初始化操作
onPageShow
- 仅对页面组件生效(也就是[@Entry](/user/Entry)修饰的组件)
- 每次显示时触发一次,可以做开屏定时器之类的操作
onBackPress
- 仅对页面组件生效(也就是[@Entry](/user/Entry)修饰的组件)
- 用户点击手机上的返回按钮时触发,可以做一些提示性弹窗
onPageHide
- 仅对页面组件生效(也就是[@Entry](/user/Entry)修饰的组件)
- 页面每隐藏时触发一次,暂没有合适的应用场景
aboutToDisappear
- 当前组件的实例被销毁之前执行,比如当前页被路由replace时
- 不能在这个时候修改状态变量
- 可以执行一些释放资源的操作
基础能力
Timer (定时器)
- setTimeout:延时执行一个函数,仅执行一次,返回延时器的ID
- clearTimeout:传入上面的ID,可以关闭此延时器
- setInterval:周期性执行一个函数,一直重复执行,直到被清除,返回ID
- clearInterval:传入上面的ID,可以清除该周期性任务
参考资料:
</markdown>JS、TS默认你会很正常啊,这本来就是一门语言,不可能你去开发APP,人家官方文档还得教你基础语法的,这两个语言又不是鸿蒙开发的,而且基础语法网上大把教程,肯定先学语法再去开发呀。
API6-API7-API8-API9-API10 明斯克舰(模型,旅游观光用),辽宁舰(瓦良格改的,实验用),山东舰(自己造的,可以开了,还是实验用),福建舰(全新设计-带电磁弹射等,初步定型),XX舰(上狠货…)
小助手感觉你很有潜力哦,活动期待看见你的身影哦~
https://developer.huawei.com/consumer/cn/forum/topic/0203112614824851486?fid=0101562279236410779
有一个问题,因为page.ets不能继承。
那么如果有多个page.ets且有一些通用的属性a,b,c。
通常我考虑继承,创建一个base.ets,把a,b,c属性放到base中。
但是api9应该怎么办呢。
不想每个page都定义一遍a,b,c属性。
导包导出去使用
我现在就是边学边复制,然后运行,改一改颜色和字体大小,看看效果
只能理解,不能记住
所有创新并非天生,过程:学习 > 复制 > 小改动 > 大改动/定制 > 思维突破/创新 :) 但是,记忆是基础,谁也绕不开:)
接触大概一周的时间了,我也遇到很多问题,大概总结一下
- 文档确实乱,而且给的示例dome里面都很基础,稍微复杂一点的功能估计都得摸索半天
- 基础组件确实太基础了,生态现在还很差,没有一些优秀的三方组件可以用,稍微复杂一点的东西都得自己写,比如一个抽屉组件,官方的SideBarContainer实在不够用,而且操作也很迷,不支持scroller,修改showSideBar的值还没有动画,类似的问题很多很多...
- 组件上下传值需要区分一下,ref的方式也没有,得用自定义Controller的方式
- 对于之前学前端的人来说,注解这个东西可能确实比较难理解,接触了这个概念以后就比较好一些了
- 编辑文件报错不够直接,特别是有时候报错会产出.js .js.map的文件,然后怎么编译都会报错,需要手动删一下
- 多层组件嵌套scroll不好使,具体原因还没找到。
- 不能直接使用[@Prop](/user/Prop) 或者 [@Link](/user/Link)的形式传递 Resource,子组件的图片组件无法显示,最好是搞个class再使用
- 没有图标的基础组件,也不支持iconfont 官方提供的图标只能下载下来,导入到项目里,自己再想办法用
- 编辑器的提示错误问题也有很多
我这边遇到的基本就上面的问题了,大部分轮子如果有社区提供,可以提升一下开发效率,可惜现在还没有,所以,还是再等等,或者自己造轮子吧,语法问题,肯定的熟悉,要不然啥也干不了。
我现在写代码没有太大问题了,头痛的还是生态问题。
新建一个系统和生态相当不易,这个大家应该能理解,要自己建造一个独立自主的体系既是不得已,也是必须的;但历史积累花时间才有积累;往好处想,现在是大家造自己的轮子的时候;不怕今后别人有轮子也不让你用的情况发生了。