1、Blank
空白填充组件,- Blank在父容器Row、Column、Flex主轴方向上未设置大小时会自动拉伸、压缩,设置了大小或容器自适应子节点大小时不会自动拉伸、压缩。
//Blank组件在横竖屏占满空余空间效果。
Column(){
Row(){
Text('BlueBooth').fontSize(18)
Blank()
Toggle({ type: ToggleType.Switch }).margin({ top: 14, bottom: 14, left: 6, right: 6 })
}.width('100%').backgroundColor(0xFFFFFF).borderRadius(15).padding({ left: 12 })
}.backgroundColor(0xEFEFEF).padding(20)
2、Divider:分割线
Column(){
Text('文本1').fontSize(18)
Divider().strokeWidth(8).color('#f00')
Text('文本1').fontSize(18)
//Round:分界线的两端是半圆;
Divider().vertical(false).strokeWidth(8).height(40).color('#0f0').lineCap(LineCapStyle.Round)
//Square:在路径末端延伸半个圆,宽度等于线宽的一半,高度等于线宽(也就是边长了一点)。
Divider().vertical(false).strokeWidth(8).height(40).color('#0f0').lineCap(LineCapStyle.Square)
//Butt
Divider().vertical(false).strokeWidth(8).height(40).color('#0f0').lineCap(LineCapStyle.Butt)
}.backgroundColor(0xEFEFEF).padding(20)
3、Toggle
组件提供勾选框样式、状态按钮样式及开关样式。
Column({ space: 10 }) {
Text('type: Switch').fontSize(12).fontColor(0xcccccc).width('90%')
Flex({ justifyContent: FlexAlign.SpaceEvenly, alignItems: ItemAlign.Center }) {
Toggle({ type: ToggleType.Switch, isOn: false })
.selectedColor('#007DFF')
.switchPointColor('#FFFFFF')
.onChange((isOn: boolean) => {
console.info('Component status:' + isOn)
})
Toggle({ type: ToggleType.Switch, isOn: true })
.selectedColor('#007DFF')
.switchPointColor('#FFFFFF')
.onChange((isOn: boolean) => {
console.info('Component status:' + isOn)
})
}
Text('type: Checkbox').fontSize(12).fontColor(0xcccccc).width('90%')
Flex({ justifyContent: FlexAlign.SpaceEvenly, alignItems: ItemAlign.Center }) {
Toggle({ type: ToggleType.Checkbox, isOn: false })
.size({ width: 20, height: 20 })
.selectedColor('#007DFF')
.onChange((isOn: boolean) => {
console.info('Component status:' + isOn)
})
Toggle({ type: ToggleType.Checkbox, isOn: true })
.size({ width: 20, height: 20 })
.selectedColor('#007DFF')
.onChange((isOn: boolean) => {
console.info('Component status:' + isOn)
})
}
Text('type: Button').fontSize(12).fontColor(0xcccccc).width('90%')
Flex({ justifyContent: FlexAlign.SpaceEvenly, alignItems: ItemAlign.Center }) {
Toggle({ type: ToggleType.Button, isOn: false }) {
Text('status button').fontColor('#182431').fontSize(12)
}.width(106)
.selectedColor('rgba(0,125,255,0.20)')
.onChange((isOn: boolean) => {
console.info('Component status:' + isOn)
})
Toggle({ type: ToggleType.Button, isOn: true }) {
Text('status button').fontColor('#182431').fontSize(12)
}.width(106)
.selectedColor('rgba(0,125,255,0.20)')
.onChange((isOn: boolean) => {
console.info('Component status:' + isOn)
})
}
}.width('100%').padding(24)
4、Checkbox
提供多选框组件,通常用于某选项的打开或关闭。
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Checkbox({ name: 'checkbox1', group: 'checkboxGroup' })
.select(true)
.selectedColor(0xed6f21)
.shape(CheckBoxShape.CIRCLE)
.onChange((value: boolean) => {
console.info('Checkbox1 change is' + value)
})
Checkbox({ name: 'checkbox2', group: 'checkboxGroup' })
.select(false)
.selectedColor(0x39a2db)
.shape(CheckBoxShape.ROUNDED_SQUARE)
.onChange((value: boolean) => {
console.info('Checkbox2 change is' + value)
})
}
5、DatePicker
日期选择器组件,用于根据指定日期范围创建日期滑动选择器。
@Entry
@Component
struct DatePickerExample {
@State isLunar: boolean = false
private selectedDate: Date = new Date('2021-08-08')
build() {
Column() {
Button('切换公历农历')
.margin({ top: 30, bottom: 30 })
.onClick(() => {
this.isLunar = !this.isLunar
})
DatePicker({
start: new Date('1970-1-1'),
end: new Date('2100-1-1'),
selected: this.selectedDate
})
.disappearTextStyle({color: Color.Gray, font: {size: '16fp', weight: FontWeight.Bold}})
.textStyle({color: '#ff182431', font: {size: '18fp', weight: FontWeight.Normal}})
.selectedTextStyle({color: '#ff0000FF', font: {size: '26fp', weight: FontWeight.Regular}})
.lunar(this.isLunar)
.onDateChange((value: Date) => {
this.selectedDate = value
console.info('select current date is: ' + value.toString())
})
}.width('100%')
}
}
6、TextPicker
// xxx.ets
class bottom {
bottom:number = 50
}
let bott:bottom = new bottom()
@Entry
@Component
struct TextPickerExample {
private select: number = 1
private apfruits: string[] = ['apple1', 'apple2', 'apple3', 'apple4']
private orfruits: string[] = ['orange1', 'orange2', 'orange3', 'orange4']
private pefruits: string[] = ['peach1', 'peach2', 'peach3', 'peach4']
private multi: string[][] = [this.apfruits, this.orfruits, this.pefruits]
private cascade: TextCascadePickerRangeContent[] = [
{
text: '辽宁省',
children: [{ text: '沈阳市', children: [{ text: '沈河区' }, { text: '和平区' }, { text: '浑南区' }] },
{ text: '大连市', children: [{ text: '中山区' }, { text: '金州区' }, { text: '长海县' }] }]
},
{
text: '吉林省',
children: [{ text: '长春市', children: [{ text: '南关区' }, { text: '宽城区' }, { text: '朝阳区' }] },
{ text: '四平市', children: [{ text: '铁西区' }, { text: '铁东区' }, { text: '梨树县' }] }]
},
{
text: '黑龙江省',
children: [{ text: '哈尔滨市', children: [{ text: '道里区' }, { text: '道外区' }, { text: '南岗区' }] },
{ text: '牡丹江市', children: [{ text: '东安区' }, { text: '西安区' }, { text: '爱民区' }] }]
}
]
build() {
Column() {
TextPicker({ range: this.apfruits, selected: this.select })
.onChange((value: string | string[], index: number | number[]) => {
console.info('Picker item changed, value: ' + value + ', index: ' + index)
}).margin(bott)
TextPicker({ range: this.multi })
.onChange((value: string | string[], index: number | number[]) => {
console.info('TextPicker 多列:onChange ' + JSON.stringify(value) + ', ' + 'index: ' + JSON.stringify(index))
}).margin(bott)
TextPicker({ range: this.cascade })
.onChange((value: string | string[], index: number | number[]) => {
console.info('TextPicker 多列联动:onChange ' + JSON.stringify(value) + ', ' + 'index: ' + JSON.stringify(index))
})
}
}
}
7、TimePicker
// xxx.ets
@Entry
@Component
struct TimePickerExample {
@State isMilitaryTime: boolean = false
private selectedTime: Date = new Date('2022-07-22T08:00:00')
build() {
Column() {
Button('切换12小时制/24小时制')
.margin(30)
.onClick(() => {
this.isMilitaryTime = !this.isMilitaryTime
})
TimePicker({
selected: this.selectedTime,
})
.useMilitaryTime(this.isMilitaryTime)
.onChange((value: TimePickerResult) => {
if(value.hour >= 0) {
this.selectedTime.setHours(value.hour, value.minute)
console.info('select current date is: ' + JSON.stringify(value))
}
})
.disappearTextStyle({color: Color.Red, font: {size: 15, weight: FontWeight.Lighter}})
.textStyle({color: Color.Black, font: {size: 20, weight: FontWeight.Normal}})
.selectedTextStyle({color: Color.Blue, font: {size: 30, weight: FontWeight.Bolder}})
}.width('100%')
}
}
8、Select
// xxx.ets
@Entry
@Component
struct SelectExample {
@State text: string = "TTTTT"
@State index: number = 2
@State space: number = 8
@State arrowPosition: ArrowPosition = ArrowPosition.END
build() {
Column() {
Select([{ value: 'aaa', icon: $r("app.media.startIcon") },
{ value: 'bbb', icon: $r("app.media.startIcon") },
{ value: 'ccc', icon: $r("app.media.startIcon") },
{ value: 'ddd', icon: $r("app.media.startIcon") }])
.selected(this.index)
.value(this.text)
.font({ size: 16, weight: 500 })
.fontColor('#182431')
.selectedOptionFont({ size: 16, weight: 400 })
.optionFont({ size: 16, weight: 400 })
.space(this.space)
.arrowPosition(this.arrowPosition)
.menuAlign(MenuAlignType.START, {dx:0, dy:0})
.optionWidth(200)
.optionHeight(300)
.onSelect((index:number, text?: string | undefined)=>{
console.info('Select:' + index)
this.index = index;
if(text){
this.text = text;
}
})
}.width('100%')
}
}
9、Slider
设置滑轨的背景颜色。
// xxx.ets
@Entry
@Component
struct SliderExample {
@State outSetValueOne: number = 40
@State inSetValueOne: number = 40
@State noneValueOne: number = 40
@State outSetValueTwo: number = 40
@State inSetValueTwo: number = 40
@State vOutSetValueOne: number = 40
@State vInSetValueOne: number = 40
@State vOutSetValueTwo: number = 40
@State vInSetValueTwo: number = 40
build() {
Column({ space: 8 }) {
Text('outset slider').fontSize(9).fontColor(0xCCCCCC).width('90%').margin(15)
Row() {
Slider({
value: this.outSetValueOne,
min: 0,
max: 100,
style: SliderStyle.OutSet
})
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.outSetValueOne = value
console.info('value:' + value + 'mode:' + mode.toString())
})
// toFixed(0)将滑动条返回值处理为整数精度
Text(this.outSetValueOne.toFixed(0)).fontSize(12)
}
.width('80%')
Row() {
Slider({
value: this.outSetValueTwo,
step: 10,
style: SliderStyle.OutSet
})
.showSteps(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.outSetValueTwo = value
console.info('value:' + value + 'mode:' + mode.toString())
})
Text(this.outSetValueTwo.toFixed(0)).fontSize(12)
}
.width('80%')
Text('inset slider').fontSize(9).fontColor(0xCCCCCC).width('90%').margin(15)
Row() {
Slider({
value: this.inSetValueOne,
min: 0,
max: 100,
style: SliderStyle.InSet
})
.blockColor('#191970')
.trackColor('#ADD8E6')
.selectedColor('#4169E1')
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.inSetValueOne = value
console.info('value:' + value + 'mode:' + mode.toString())
})
Text(this.inSetValueOne.toFixed(0)).fontSize(12)
}
.width('80%')
Row() {
Slider({
value: this.inSetValueTwo,
step: 10,
style: SliderStyle.InSet
})
.blockColor('#191970')
.trackColor('#ADD8E6')
.selectedColor('#4169E1')
.showSteps(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.inSetValueTwo = value
console.info('value:' + value + 'mode:' + mode.toString())
})
Text(this.inSetValueTwo.toFixed(0)).fontSize(12)
}
.width('80%')
Text('none slider').fontSize(9).fontColor(0xCCCCCC).width('90%').margin(15)
Row() {
Slider({
value: this.noneValueOne,
min: 0,
max: 100,
style: SliderStyle.NONE
})
.blockColor('#191970')
.trackColor('#ADD8E6')
.selectedColor('#4169E1')
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.noneValueOne = value
console.info('value:' + value + 'mode:' + mode.toString())
})
Text(this.noneValueOne.toFixed(0)).fontSize(12)
}
.width('80%')
Row() {
Column() {
Text('vertical outset slider').fontSize(9).fontColor(0xCCCCCC).width('50%').margin(15)
Row() {
Text().width('10%')
Slider({
value: this.vOutSetValueOne,
style: SliderStyle.OutSet,
direction: Axis.Vertical
})
.blockColor('#191970')
.trackColor('#ADD8E6')
.selectedColor('#4169E1')
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.vOutSetValueOne = value
console.info('value:' + value + 'mode:' + mode.toString())
})
Slider({
value: this.vOutSetValueTwo,
step: 10,
style: SliderStyle.OutSet,
direction: Axis.Vertical
})
.blockColor('#191970')
.trackColor('#ADD8E6')
.selectedColor('#4169E1')
.showSteps(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.vOutSetValueTwo = value
console.info('value:' + value + 'mode:' + mode.toString())
})
}
}.width('50%').height(300)
Column() {
Text('vertical inset slider').fontSize(9).fontColor(0xCCCCCC).width('50%').margin(15)
Row() {
Slider({
value: this.vInSetValueOne,
style: SliderStyle.InSet,
direction: Axis.Vertical,
reverse: true // 竖向的Slider默认是上端是min值,下端是max值,因此想要从下往上滑动,需要设置reverse为true
})
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.vInSetValueOne = value
console.info('value:' + value + 'mode:' + mode.toString())
})
Slider({
value: this.vInSetValueTwo,
step: 10,
style: SliderStyle.InSet,
direction: Axis.Vertical,
reverse: true
})
.showSteps(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.vInSetValueTwo = value
console.info('value:' + value + 'mode:' + mode.toString())
})
}
}.width('50%').height(300)
}
}.width('100%')
}
}
10、Search
搜索框组件,适用于浏览器的搜索内容输入框等应用场景。
// xxx.ets
@Entry
@Component
struct SearchExample {
@State changeValue: string = ''
@State submitValue: string = ''
@State positionInfo: CaretOffset = { index: 0, x: 0, y: 0 }
controller: SearchController = new SearchController()
build() {
Column({space: 10}) {
Text('onSubmit:' + this.submitValue).fontSize(18).margin(15)
Text('onChange:' + this.changeValue).fontSize(18).margin(15)
Search({ value: this.changeValue, placeholder: 'Type to search...', controller: this.controller })
.searchButton('SEARCH')
.width('95%')
.height(40)
.backgroundColor('#F5F5F5')
.placeholderColor(Color.Grey)
.placeholderFont({ size: 14, weight: 400 })
.textFont({ size: 14, weight: 400 })
.onSubmit((value: string) => {
this.submitValue = value
})
.onChange((value: string) => {
this.changeValue = value
})
.margin(20)
Button('Set caretPosition 1')
.onClick(() => {
// 设置光标位置到输入的第一个字符后
this.controller.caretPosition(1)
})
Button('Get CaretOffset')
.onClick(() => {
this.positionInfo = this.controller.getCaretOffset()
})
}.width('100%')
}
}
11、web
展示网页内容的组件。
// xxx.ets
import webview from '@ohos.web.webview';
@Entry
@Component
struct Index {
webCtr : webview.WebviewController = new webview.WebviewController();
build() {
Column() {
Web({
src:'https://www.baidu.com/'
, controller : this.webCtr
})
}
}
}
12、路由使用
//1.引入路由
import router from '@ohos.router'
//2.使用跳转
router.pushUrl({
url: "pages/Show"
})
//延迟跳转
setTimeout(() => {
//跳转到数据展示页面
router.pushUrl({
url: "pages/Show"
})
},2000)
13、布局-grid布局
// Grid布局的基本使用: 规则的行列布局中非常常见, 3行4列
Grid() {
ForEach([1,2,3,4,5,6,7,8,9,10,11,12], () => {
GridItem() {
Column() {
}
.width('100%')
.height('100%')
.backgroundColor(Color.Green)
.border({ width: 1 })
}
})
}
//设置多少列
.columnsTemplate('1fr 1fr 1fr 1fr')
//设置多少行
.rowsTemplate('1fr 1fr 1fr')
.columnsGap(6)
.rowsGap(6)
.width('100%')
.height(500)
.backgroundColor(Color.Pink)
14、层叠布局
// 层叠布局
Stack({
alignContent: Alignment.Bottom
}) {
Text('大儿子')
.width(250)
.height(250)
.backgroundColor(Color.Green)
.zIndex(3)
Text('二儿子')
.width(150)
.height(150)
.backgroundColor(Color.Orange)
.zIndex(4)
Text('三儿子')
.width(50)
.height(50)
.backgroundColor(Color.Yellow)
.zIndex(5)
}
.width(300)
.height(600)
.backgroundColor(Color.Pink)
15、动画-动画特效
16、模块化-导入,导出模块
// 路径: 查找文件时, 从起点到终点的路线
// 相对路径: 从当前文件出发查找目标文件
// → 找上一级 ../
// → 同级目录 ./
// 1. 默认导入
// import result from '../tools/module1'
// import fn from './module2'
// console.log('module1中的数据', JSON.stringify(result))
// fn()
// 2. 按需导入
// import { name1, price, sayHi as sayHello } from '../tools/module3'
// console.log('module3中的数据', name1, price)
// sayHello()
// 3. 全部导入
import * as Module3 from '../tools/module3'
console.log('全部的数据', Module3.name1)
console.log('全部的数据', Module3.price2)
Module3.sayHi()
--------------------------默认导出------------------
interface Person {
name: string
age: number
}
// 一个ets文件, 就是一个模块, 每个模块之间独立
let num: number = 10
let person: Person = {
name: 'jack',
age: 18
}
// 默认导出 (导出一个值)
export default person
--------------------------按需导出------------------------
// 按需导出
// 多个特性, 逐个 export 按需导出
// export let name1: string = '刘备'
// export let price: number = 9.98
// export let sayHi = () => {
// console.log('打招呼')
// }
let name1: string = '刘备'
let name2: string = '张飞'
let name3: string = '关羽'
let price: number = 9.98
let price2: number = 10.1
let sayHi = () => {
console.log('打招呼')
}
let run = () => {
console.log('跑步')
}
// 一次性将多个特性, 进行导出
export {
name1, name2, name3,
price, price2,
sayHi, run
}
17、注解-@Entry
在ArkUI 中,@Entry和@Component是两个非常重要的装饰器,@Entry装饰器用于指定应用程序的入口,应用程序启动时将首先加载该组件,而@Component装饰器则用于创建自定义的UI组件。
在ArkUI的示例代码中,通常使用struct来声明一个自定义UI组件,并在build()函数中描述该组件的内容。
@Entry
@Component
struct TextView {
build() {
// 视图代码
}
}
18、注解-@Extend 扩展特定组件样式
// @Extend(组件名)
// function 函数名 (参数, 参数2) {
//
// }
@Extend(Text)
function textFn () {
.fontSize(20)
.fontWeight(FontWeight.Bold)
}
@Extend(Text)
function bannerItem (bgColor: ResourceColor, msg: string) {
.textAlign(TextAlign.Center)
.backgroundColor(bgColor)
.fontColor(Color.White)
.fontSize(30)
.onClick(() => {
AlertDialog.show({
message: msg
})
})
}
----------------------------调用------------------------------
Text(this.message)
.textFn()
Swiper() {
Text('1')
.bannerItem(Color.Orange, '轮播图1号')
Text('2')
.bannerItem(Color.Brown, '轮播图2号')
Text('3')
.bannerItem(Color.Green, '轮播图3号')
}
.width('100%')
.height(160)
18、注解-@Styles 通用组件设置值
// 1. 全局定义
@Styles function commonStyles () {
.width(100)
.height(100)
}
@Entry
@Component
struct StylesDemo {
@State message: string = '@styles';
@State bgColor: ResourceColor = Color.Gray
// 2. 组件内定义(才能通过this访问到自己的状态)
@Styles setBg() {
.backgroundColor(this.bgColor)
.onClick(() => {
this.bgColor = Color.Pink
})
}
build() {
Column({ space: 10 }) {
Text(this.message)
.fontColor(Color.White)
.commonStyles()
.setBg()
Column() {}
.commonStyles()
.setBg()
Button('按钮')
.commonStyles()
.setBg()
}
.width('100%')
.height('100%')
}
}
19、注解-@Builder 构建一个全局组件
// 全局 Builder
@Builder
function navItem(icon: ResourceStr, txt: string) {
Column({ space: 10 }) {
Image(icon)
.width('80%')
Text(txt)
}
.width('25%')
.onClick(() => {
AlertDialog.show({
message: '点了' + txt
})
})
}
@Entry
@Component
struct BuilderDemo {
@State message: string = '@Builder';
//定义一个全局的组件
@Builder
navItem(icon: ResourceStr, txt: string) {
Column({ space: 10 }) {
Image(icon)
.width('80%')
Text(txt)
}
.width('25%')
.onClick(() => {
AlertDialog.show({
message: '点了' + txt + this.message
})
})
}
//文本的开始
build() {
Column({ space: 20 }) {
Text(this.message)
.fontSize(30)
Row() {
Row() {
navItem($r('app.media.bg_001'), '阿里拍卖')
navItem($r('app.media.bg_002'), '菜鸟')
this.navItem($r('app.media.bg_003'), '巴巴农场')
this.navItem($r('app.media.bg_004'), '阿里药房')
}
}
}
.width('100%')
.height('100%')
}
}
20、注解-@Component 模块复用1
@Component
struct MyHeader {
build() {
Row() {
Text('我是头部')
.fontColor(Color.White)
}
.width('100%')
.height(50)
.backgroundColor(Color.Brown)
}
}
@Component
struct MyCom {
@State count: number = 1
build() {
Row() {
Text(this.count.toString())
.fontColor(Color.White)
.margin(10)
Button('按钮')
.onClick(() => {
this.count++
})
}
}
}
@Component
struct MyMain {
build() {
Column() {
// 将相同的业务逻辑, 封装成一个通用的组件
MyCom()
MyCom()
MyCom()
}
.layoutWeight(1)
.width('100%')
.backgroundColor(Color.Gray)
}
}
@Component
struct MyFooter {
build() {
Row() {
Text('我是底部')
}
.width('100%')
.height(50)
.backgroundColor(Color.Green)
}
}
@Entry
@Component
struct Index {
build() {
Column() {
MyHeader()
MyMain()
MyFooter()
}
}
}
21、注解-@Component 模块复用2
- 1、在components文件下创建HelloCom
//---------------------------------------1.导出组件------------------
//加入这个@Preview可以预览页面
@Preview
@Component
export struct HelloCom {
build() {
Row() {
Text('自定义组件')
Button('按钮')
}
.width(200)
.height(50)
.backgroundColor(Color.Orange)
}
}
- 2、在components文件下创建Index 并导入HelloCom
//-----------------------------------2.导入组件----------------------------
import { HelloCom } from '../components/HelloCom'
@Entry
@Component
struct Index {
build() {
Column() {
HelloCom()
.width(250)
.height(60)
.backgroundColor(Color.Gray)
.onClick(() => {
AlertDialog.show({
message: '测试点击'
})
})
}
}
}
22、注解-@Component 模块复用3
//公共模块
@Component
struct MyPanel {
// 成员变量 - 数据
title: string = '默认的大标题'
extra: string = '查看更多 >'
// 成员变量 - 函数 - 可以外部传入覆盖的
getMore = () => {
AlertDialog.show({
message: '查看更多'
})
}
// 成员函数 - 不可以外部传入覆盖
sayHi() {
AlertDialog.show({
message: '打招呼, 你好'
})
}
build() {
Column() {
Row() {
Text(this.title).fontSize(18)
Text(this.extra).fontSize(18)
.onClick(() => {
this.getMore()
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
Row() {
Text('内容部分').fontSize(18)
Button('按钮')
.onClick(() => {
this.sayHi()
})
}
.padding(20)
}
.padding(10)
.width('100%')
.height(200)
.margin({ bottom: 20 })
.borderRadius(10)
.backgroundColor(Color.White)
}
}
//-------------------------------分割线------------------------------------
//调用公共方法
@Entry
@Component
struct Index {
build() {
Column() {
MyPanel({
title: '我的订单',
extra: '全部订单 > ',
getMore() {
AlertDialog.show({
message: '点击了全部订单'
})
}
})
MyPanel({
title: '小米有品重酬',
extra: '7款重酬中 >',
getMore() {
AlertDialog.show({
message: '查看7款重酬'
})
}
})
}
.width('100%')
.height('100%')
.backgroundColor('#ccc')
.padding(20)
}
}
23、注解-@BuilderParam 可以让自定义组件外部传递UI,相当于vue的插槽(单个参数)
@Component
struct MyPanel {
// 成员变量 - 数据
title: string = '默认的大标题'
extra: string = '查看更多 >'
// 成员变量 - 函数 - 可以外部传入覆盖的
getMore = () => {
AlertDialog.show({
message: '查看更多'
})
}
// 成员函数 - 不可以外部传入覆盖
sayHi() {
AlertDialog.show({
message: '打招呼, 你好'
})
}
//定义BuilderParam的方法
@BuilderParam ContentBuilder: () => void = this.defaultBuilder
@Builder defaultBuilder () {
Text('默认文本')
}
build() {
Column() {
Row() {
Text(this.title).fontSize(18)
Text(this.extra).fontSize(18)
.onClick(() => {
this.getMore()
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
Row() {
// 这里的结构不能写死, 需要通过 BuilderParam 来进行构建
this.ContentBuilder()
}
.padding(20)
}
.padding(10)
.width('100%')
.height(200)
.margin({ bottom: 20 })
.borderRadius(10)
.backgroundColor(Color.White)
}
}
@Entry
@Component
struct Index {
build() {
Column() {
MyPanel({
title: '我的订单',
extra: '全部订单 > ',
getMore() {
AlertDialog.show({
message: '点击了全部订单'
})
}
}) {
Column() {
Text('我是订单 - 相关的文本')
Text('我是订单 - 相关的文本').margin(5)
Text('我是订单 - 相关的文本')
}
}
MyPanel({
title: '小米有品重酬',
extra: '7款重酬中 >',
getMore() {
AlertDialog.show({
message: '查看7款重酬'
})
}
}) {
Column() {
Button('我是小米重酬的按钮')
Button('我是小米重酬的按钮').margin(5)
Button('我是小米重酬的按钮')
}
}
}
.width('100%')
.height('100%')
.backgroundColor('#ccc')
.padding(20)
}
}
24、注解-@BuilderParam 可以让自定义组件外部传递UI,相当于vue的插槽(多个参数)
//定义MyCard的卡片
@Component
struct MyCard {
@BuilderParam tBuilder: () => void = this.tDefaultBuilder
@BuilderParam cBuilder: () => void = this.cDefaultBuilder
@Builder tDefaultBuilder () {
Text('我是默认的大标题')
}
@Builder cDefaultBuilder () {
Text('我是默认的内容')
}
build() {
// 卡片组件
Column() {
// 标题部分
Row() {
this.tBuilder()
}
.height(30)
.width('100%')
.border({ color: '#ccc', width: { bottom: 1 }})
.padding({ left: 10 })
// 内容部分
Row() {
this.cBuilder()
}
.width('100%')
.padding(10)
}
.width('100%')
.height(100)
.backgroundColor(Color.White)
.borderRadius(10)
.justifyContent(FlexAlign.Start)
}
}
//方法调用
@Entry
@Component
struct Index {
@Builder ftBuilder () {
Text('我是传入的大标题结构').fontSize(20).fontColor(Color.Red)
}
@Builder fcBuilder () {
Text('我是内容部分')
Text('我是内容部分')
Text('我是内容部分')
}
build() {
Column({ space: 10 }) {
MyCard()
MyCard({
tBuilder: this.ftBuilder,
cBuilder: this.fcBuilder
})
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor('#ccc')
}
}
25、注解-@State 状态变量
- 1、简单的变量赋值:
// 注意点:
// 1. 普通变量, 只能在初始化时渲染, 后续变化了, 也不会引起更新
// 2. 状态变量, 被装饰器修饰, 值的改变, 会 [自动] 引起 界面的刷新
// 组件外的[普通变量] 不需要this即可访问
let myName: string = '吕布'
@Entry
@Component
struct Index {
// 组件内的[普通变量] this.xxx
myAge: number = 18
// 组件内的[状态变量] this.xxx
@State myMsg: string = 'hello 黑马'
build() {
Column() {
Button(myName).onClick(() => {
myName = '貂蝉'
console.log('myName', myName)
})
Button(this.myAge.toString()).onClick(() => {
this.myAge = 200
console.log('myAge', this.myAge)
}).margin(5)
Button(this.myMsg).onClick(() => {
this.myMsg = '我已经变成白马了'
console.log('myMsg', this.myMsg)
})
}
}
}
- 2、复杂的变量赋值:
interface Car {
name: string
}
interface Person {
name: string
car: Car
}
const obj: Person = {
name: 'zs',
car: {
name: '小黄车'
}
}
console.log('查看第一层属性', Object.keys(obj))
//调用
@Entry
@Component
struct Index {
// 状态变量
// 1. string number boolean 可以直接监视到变化
@State message: string = 'hello world'
// 2. 复杂类型 object class, 第一层随便改, 嵌套需要进行整个嵌套对象的替换
@State person: Person = {
name: 'jack',
car: {
name: '宝马车'
}
}
build() {
Column() {
Text(this.message).fontSize(20)
Button('改message').onClick(() => {
this.message = '你好'
})
Text(JSON.stringify(this.person)).margin({top:20})
Button('改person').onClick(() => {
// this.person = {
// name: 'amy',
// car: {
// name: '保时捷'
// }
// }
this.person.name = 'tony'
// 如果不是对象的第一层属性, 修改时, 需要修改整个嵌套的对象
this.person.car.name = '小火车'
// console.log('car name', this.person.car.name)
this.person.car = {
name: '老爷车'
}
})
}
}
}
26、注解-@Prop父传子,让值变化
//@Prop加了这个后,父组件更改这个值,子组件也会跟着变化
@Component
struct SonCom {
// 保证父组件的数据变化了, 能够往下响应式的更新
@Prop sCar: string = ''
changeCar = (newCar: string) => {}
build() {
Column() {
Text(`子组件 ${this.sCar}`)
Button('换车').onClick((event: ClickEvent) => {
// 1. prop传值 → 单向传递
// 子组件, 可以修改到 prop 传值, 但是修改的更新不会同步到父组件
// 通常不太会直接修改 prop 传值, 父组件的状态一旦变化, 会自动向下同步
// 修改就被覆盖了
// this.sCar = '小黄车'
// 2. 如果实在想更新, 希望保证父子同步 => 调用父组件传递过来的方法
// 如果没有写箭头函数, 意味着, this 指向 调用者, 而此处执行环境 this → 子组件
this.changeCar('蹦蹦车')
})
}
.padding(20)
.backgroundColor(Color.Orange)
}
}
@Entry
@Component
struct FatherCom {
@State fCar:string = '劳斯莱斯'
build() {
Column() {
Text(`父组件 - ${this.fCar}`)
Button('换车').onClick(() => {
this.fCar = '三轮车'
})
SonCom({
sCar: this.fCar,
// 这里必须要用箭头函数, 否则会有 this 指向的问题
// 使用箭头函数的好处, 可以使用外部环境的 this, 不受传递过去后的执行环境影响
// 希望此处 this 指向 父组件
changeCar: (newCar: string) => {
this.fCar = newCar
}
})
}
.padding(50)
.backgroundColor(Color.Pink)
}
}
27、注解-@Link 父传子 子传父,数据双向同步
interface Person {
name: string
age: number
}
@Entry
@Component
// 父组件
struct KnowledgePage {
@State count: number = 0
@State person: Person = {
name: 'zs',
age: 18
}
build() {
Column() {
Text('父组件')
.fontSize(30)
Text(this.count.toString())
Text(JSON.stringify(this.person))
Button('修改数据')
.onClick(() => {
this.count++
})
SonComponent({
count: this.count,
person: this.person
})
}
.padding(10)
.height('100%')
.backgroundColor('#eee')
.width('100%')
.alignItems(HorizontalAlign.Center)
.padding({ top: 100 })
}
}
@Component
// 子组件
struct SonComponent {
@Link count: number
@Link person: Person
// 编写 UI
build() {
Column({ space: 20 }) {
Text('我是子组件')
.fontSize(20)
Text(this.count.toString())
Text(JSON.stringify(this.person))
Column() {
Button('修改数据')
.onClick(() => {
// this.count++
this.person.age++
})
}
}
.backgroundColor('#a6c398')
.alignItems(HorizontalAlign.Center)
.width('80%')
.margin({ top: 100 })
.padding(10)
.borderRadius(10)
}
}
28、注解- @Consume和@Provide父与子孙后代简单数据同步
interface Car {
name: string
brand: string
}
@Entry
@Component
// 顶级组件
struct RootComponent {
@Provide themeColor: string = 'yellow'
@Provide car: Car = {
name: '小黄',
brand: '美团'
}
build() {
Column() {
Text('顶级组件')
.fontSize(30)
.fontWeight(900)
Text(this.themeColor)
Text(JSON.stringify(this.car))
// 二级组件
ParentComponent()
ParentComponent()
}
.padding(10)
.height('100%')
.backgroundColor('#ccc')
.width('100%')
.alignItems(HorizontalAlign.Center)
.padding({ top: 30 })
}
}
@Component
// 二级组件
struct ParentComponent {
@Consume themeColor: string
// 编写 UI
build() {
Column({ space: 20 }) {
Text('我是二级组件')
.fontSize(22)
.fontWeight(900)
Text(this.themeColor)
// 内层子组件
SonComponent()
}
.backgroundColor('#a6c398')
.alignItems(HorizontalAlign.Center)
.width('90%')
.margin({ top: 50 })
.padding(10)
.borderRadius(10)
}
}
@Component
// 内层组件
struct SonComponent {
@Consume themeColor: string
@Consume car: Car
// 编写 UI
build() {
Column({ space: 20 }) {
Text('我是内层组件' + this.themeColor)
.fontSize(20)
.fontWeight(900)
.onClick(() => {
// this.themeColor = 'orange'
this.car.name = '小绿'
})
Text(JSON.stringify(this.car))
}
.backgroundColor('#bf94e4')
.alignItems(HorizontalAlign.Center)
.width('90%')
.margin({ top: 50 })
.padding(10)
.borderRadius(10)
}
}
29、注解- @Observed和@ObjectLink父与子孙后代复杂数据同步(多层数据)
interface IPerson {
id: number
name: string
age: number
}
@Observed
class Person {
id: number
name: string
age: number
constructor(obj: IPerson) {
this.id = obj.id
this.name = obj.name
this.age = obj.age
}
}
@Entry
@Component
struct ObservedAndLink {
@State personList: Person[] = [
new Person({
id: 1,
name: '张三',
age: 18
}),
new Person({
id: 2,
name: '李四',
age: 19
}),
new Person({
id: 3,
name: '王五',
age: 20
})
]
build() {
Column({ space: 20 }) {
Text('父组件')
.fontSize(30)
List({ space: 10 }) {
ForEach(this.personList, (item: Person, index: number) => {
ItemCom({
info: item,
addAge: () => {
// 修改嵌套的数据 => 普通的情况, 监视不到更新
item.age++ // 如果能监视到
AlertDialog.show({
message: JSON.stringify(this.personList)
})
// this.personList.splice(index, 1, item) // 无需手动替换更新
}
})
})
}
}
.backgroundColor('#cbe69b')
.width('100%')
.height('100%')
.padding(20)
}
}
@Component
struct ItemCom {
@ObjectLink info: Person
addAge = () => {
}
build() {
ListItem() {
Row({ space: 10 }) {
Text('姓名:' + this.info.name)
Text('年龄:' + this.info.age)
Blank()
Button('修改数据')
.onClick(() => {
// this.addAge()
this.info.age++
})
}
.backgroundColor(Color.Pink)
.padding(10)
.width('100%')
}
}
}