一、布局鸿蒙ArkUI采用声明式布局体系,所有页面都遵循「一个根布局,根布局内可嵌套多层子布局」的规则,下面为你逐个讲解常用布局:

1. 垂直布局 Column

Column是最常用的垂直排列容器,所有子元素会沿着垂直方向从上到下依次排列,可以通过属性控制对齐方式和元素间距,非常适合做页面的根容器、表单列表排列。属性‌:space:设置所有子元素之间的统一间距justifyContent:控制子元素在‌垂直方向‌的对齐方式,常用值:Start(顶部对齐,默认)、Center(居中对齐)、End(底部对齐)、SpaceBetween(均匀分布,首尾不留空)、SpaceAround(均匀分布,首尾留半空)

alignItems:控制子元素在‌水平方向‌的对齐方式,常用值:Start(左对齐)、Center(居中对齐)、End(右对齐)

代码示例:

@Entry

@Component

struct VerticalDemo {

build() {

Column({ space: 10 }) {

Text("第一条内容")

        .fontSize(20)

        .width('100%')

        .backgroundColor('#f0f0f0')

Text("第二条内容")

        .fontSize(20)

        .width('100%')

        .backgroundColor('#e0e0e0')

Text("第三条内容")

        .fontSize(20)

        .width('100%')

        .backgroundColor('#f0f0f0')

    }

    .width('100%')

    .padding(15)

    .alignItems(HorizontalAlign.Start) 

  }

}

垂直布局示例代码运行效果图:

2. 水平布局 Row
Row是水平排列容器,所有子元素会沿着水平方向从左到右依次排列,适合做顶部导航栏、按钮组、横向表单项目排列。

属性‌:

space
:设置所有子元素之间的统一水平间距
justifyContent
:控制子元素在‌水平方向‌的对齐方式,取值和Column一致
alignItems
:控制子元素在‌垂直方向‌的对齐方式,常用值:Top(顶部对齐)、Center(居中对齐)、Bottom(底部对齐)
代码示例:

@Entry
@Component
struct HorizontalDemo {
build() {
Row({ space: 12 }) { // 水平排列,元素间距12vp
Button("首页")
Button("分类")
Button("我的")
    }
    .width('100%')
    .height(50)
    .backgroundColor('#fff')
    .justifyContent(FlexAlign.Center) // 水平居中排列
    .alignItems(VerticalAlign.Center) // 垂直居中对齐
  }
}

 水平布局对齐方式示例效果图

3. 相对布局 RelativeContainer

相对布局是自由度极高的布局方式,允许子组件‌基于父容器,或者其他子组件设置对齐规则‌来确定位置,非常适合实现复杂的不规则页面布局,是鸿蒙开发中处理复杂界面的核心布局。

用法‌:

给每个需要定位的子组件设置唯一id

通过alignRules配置对齐规则:可以设置left(左边缘对齐)、right(右边缘对齐)、top(上边缘对齐)、bottom(下边缘对齐),规则内容为anchor: '组件id'表示对齐到对应组件的对应边缘

代码示例:

@Entry

@Component

struct RelativeDemo {

build() {

RelativeContainer() {

// 床1:靠左上角

Text("1号床")

        .size({width: 100, height: 100})

        .backgroundColor(Color.Pink)

        .alignRules({

left: {anchor: '__container__', align: RelativeAlign.Left},

top: {anchor: '__container__', align: RelativeAlign.Top}

        })

        .id("bed1")



// 床2:床1的右侧,顶部和床1对齐

Text("2号床")

        .size({width: 100, height: 100})

        .backgroundColor(Color.Blue)

        .alignRules({

left: {anchor: 'bed1', align: RelativeAlign.Right},

top: {anchor: 'bed1', align: RelativeAlign.Top}

        })

        .id("bed2")

    }

    .size({width: '100%', height: 400})

    .padding(10)

  }

}

(__container__代表根容器自身,代表对齐到父容器)

相对布局宿舍床位示例运行效果图

4. 层叠布局 Stack

Stack是层叠容器,子组件会按照代码顺序‌依次堆叠‌,后面写的组件会覆盖在前面的组件上方,非常适合实现「图片上飘文字」、「卡片角标」、「悬浮按钮」这类需要叠加元素的场景。

属性‌:

alignContent:设置所有子元素整体的对齐方式

支持给子元素单独设置position,做绝对定位

代码示例:

@Entry

@Component

struct StackDemo {

build() {

Stack({ alignContent: Alignment.BottomEnd }) {

// 底层:卡片内容

Column() {

Text("课程卡片")

          .fontSize(18)

      }

      .width('90%')

      .height(200)

      .backgroundColor(Color.White)

      .borderRadius(12)



// 上层:悬浮按钮,叠在右下角

Button("+")

        .width(40)

        .height(40)

        .borderRadius(20)

        .margin({ right: 10, bottom: 10 })

    }

    .width('100%')

    .height(250)

    .padding(10)

  }

}

层叠布局悬浮按钮示例运行效果图

5. 弹性布局 Flex

 Flex是流式弹性布局,相比Row/Column更灵活,支持设置换行,自动分配子元素空间,非常适合实现标签流、不规则网格、响应式排列这类场景。

 属性‌:

direction:设置主轴方向(水平还是垂直排列)

wrap:设置是否换行,FlexWrap.Wrap代表自动换行,超出主轴宽度自动切到下一行,实现流式布局

justifyContent

、alignItems:和Row/Column类似,控制主轴和交叉轴的对齐方式

代码示例:

@Entry

@Component

struct FlexDemo {

build() {

Flex({ wrap: FlexWrap.Wrap, space: { mainAxis: 10, crossAxis: 10 } }) {

// 多个标签自动换行

Text("鸿蒙开发")

        .padding({ left: 12, right: 12, top: 6, bottom: 6 })

        .backgroundColor('#e0f0ff')

        .borderRadius(16)

Text("ArkTS")

        .padding({ left: 12, right: 12, top: 6, bottom: 6 })

        .backgroundColor('#e0f0ff')

        .borderRadius(16)

Text("布局学习")

        .padding({ left: 12, right: 12, top: 6, bottom: 6 })

        .backgroundColor('#e0f0ff')

        .borderRadius(16)

// 更多标签...

    }

    .padding(15)

  }

}

弹性布局标签按钮流式排列效果图

二、组件

布局是页面的骨架,组件就是页面的血肉,常用基础组件如下:

1. 轮播图 Swiper

Swiper是鸿蒙提供的原生轮播组件,专门用来做首页banner轮播、图片漫游等需要滑动切换的场景,支持自动播放、循环滚动、自定义指示器。

属性:

autoPlay:是否自动轮播,布尔值

loop:是否循环滚动,布尔值

interval:自动轮播的切换间隔,单位毫秒

indicator:是否显示指示点,布尔值

代码示例:

@Entry

@Component

struct SwiperDemo {

build() {

Swiper() {

Image($r('app.media.banner1')) // 第一张轮播图

        .width('100%')

        .height(200)

        .objectFit(ImageFit.Cover)



Image($r('app.media.banner2')) // 第二张轮播图

        .width('100%')

        .height(200)

        .objectFit(ImageFit.Cover)



Image($r('app.media.banner3')) // 第三张轮播图

        .width('100%')

        .height(200)

        .objectFit(ImageFit.Cover)

    }

    .autoPlay(true)

    .loop(true)

    .interval(3000)

    .indicator(true)

    .width('100%')

    .height(200)

    .margin(15)

  }

}

Swiper图片轮播示例运行效果图(需要准备对应banner图片资源)

2. 视频 Video

Video是原生视频播放组件,支持播放本地、网络视频,自带控制栏,也可以通过控制器自定义控制播放、暂停、进度跳转。

属性:

src:指定视频源,本地视频用$rawfile('视频文件名.mp4')读取资源文件,网络视频直接填url

controller:创建一个VideoController对象来控制视频播放

代码示例:

import video from'@ohos.multimedia.video';

 @Entry
 @Component
 struct Index  {
   private controller:VideoController = new VideoController();
   private previewUri:Resource = $r('app.media.img')
   build() {
     Column({space:20}) {
       Text("播放视频")
       Video({
         src: $rawfile('34.mp4'),
         controller: this.controller,
         previewUri: this.previewUri
       })
         .muted(true)
         .controls(true)
         .loop(true)
         .autoPlay(false)
         .width('100%')
         .height(220)
         .objectFit(ImageFit.Contain)

     
       Row({space:30}){
         Button("播放")
           .width(70)
           .height(50)
           .onClick(()=>{
             this.controller.start()
           })
         Button("暂停")
           .width(70)
           .height(50)
           .onClick(()=>{
             this.controller.pause()
           })
       }
     } 
   }
 }

Video视频播放界面运行效果图

3. 图片 Image

 Image用来展示本地或网络图片,鸿蒙中读取本地资源一般通过$r('app.media.图片名')的语法引用。

 属性‌:

objectFit:设置图片的缩放模式,ImageFit.Cover按比例铺满容器、ImageFit.Contain完整显示整个图片

代码示例:

// 加载本地资源图片

Image($r('app.media.avatar'))

  .width(80)

  .height(80)

  .borderRadius(40) // 设置圆角实现圆形头像

  .objectFit(ImageFit.Cover)



// 加载网络图片

Image('https://example.com/demo.jpg')

  .width('100%')

  .height(200)

4. 选项卡 Tabs + TabContent

 Tabs是底部/顶部选项卡容器,搭配TabContent实现多页面切换,是很多App首页框架的标配。

属性:

barPosition:设置标签栏位置,BarPosition.End放在底部,BarPosition.Start放在顶部

每个TabContent对应一个选项卡页面,通过tabBar设置选项卡标题和样式

代码示例:

@Entry

@Component

struct TabsDemo {

@StatecurrentIndex: number = 0;

build() {

Tabs({ barPosition: BarPosition.End }) {

TabContent() {

// 首页内容写在这里

Text("首页内容")

      }.tabBar("首页")



TabContent() {

// 推荐内容写在这里

Text("推荐内容")

      }.tabBar("推荐")



TabContent() {

// 我的内容写在这里

Text("我的内容")

      }.tabBar("我的")

    }

    .width('100%')

    .height('100%')

  }

}

多标签App框架运行效果图

5. 文本/输入框 Text + TextInput

Text:展示静态文本,支持设置丰富的字体样式、背景、边框、间距

TextInput:单行文本输入框,是表单收集信息的核心组件,支持设置输入类型(普通/密码)、占位提示

 属性:

placeholder:未输入时的占位提示文字

type:输入类型,InputType.Password代表密码输入,会隐藏内容

onChange:输入内容变化时触发回调,可以拿到最新输入内容

代码示例:

@Entry

@Component

struct FormDemo {

@Stateusername: string = '';

@Statepassword: string = '';

build() {

Column({ space: 15 }) {

Text("账号")

        .fontSize(16)

        .width('100%')



TextInput({ placeholder: '请输入账号', text: this.username })

        .width('100%')

        .height(40)

        .onChange((val) => {

this.username = val; // 输入内容变化同步到状态变量

        })



Text("密码")

        .fontSize(16)

        .width('100%')



TextInput({ placeholder: '请输入密码', text: this.password })

        .width('100%')

        .height(40)

        .type(InputType.Password)

        .onChange((val) => {

this.password = val;

        })

    }

    .padding(15)

  }

}

登录注册表单输入框运行效果图

6. 按钮 Button

 按钮是最核心的交互组件,用户点击后触发对应的操作,支持设置按钮样式、圆角、背景色。

代码示例:

// 普通按钮

Button("登录")

  .width('90%')

  .height(45)

  .fontSize(16)

  .backgroundColor('#007dff')

  .borderRadius(8)

  .onClick(() => {

// 点击后执行的逻辑写在这里

console.log("用户点击了登录按钮");

  })

多种样式按钮示例运行效果图

7. 单选框 Radio

 单选框用于‌多选一‌的场景,同一个分组内的单选框只能选中一个,所有单选框必须设置同一个group分组名。

 每个Radio绑定一个value,通过onChange回调判断是否选中当前选项。

代码示例:

@Entry

@Component

struct RadioDemo {

@Stategender: string = 'male';

build() {

Row({ space: 30 }) {

Text("性别:")

Row({ space: 8 }) {

Radio({ value: 'male', group: 'gender' })

          .checked(this.gender === 'male')

          .onChange(() => {

this.gender = 'male'

          })

Text("男")

      }



Row({ space: 8 }) {

Radio({ value: 'female', group: 'gender' })

          .checked(this.gender === 'female')

          .onChange(() => {

this.gender = 'female'

          })

Text("女")

      }

    }

    .alignItems(VerticalAlign.Center)

  }

}

表单单选框选项运行效果图

图片

8. 切换组件 Toggle

 Toggle是切换类组件,分为两种类型:ToggleType.Switch滑动开关(用于开/关功能切换)、ToggleType.Checkbox复选框(用于多选场景),支持状态联动,切换状态时可以自动更新UI。

isOn

绑定状态变量,表示开关是否打开

onChange

回调接收最新的开关状态,更新到状态变量中

代码示例:

@Entry

@Component

struct ToggleDemo {

@Stateopen: boolean = false;

build() {

Column({ space: 15 }) {

Text(this.open ? "夜间模式已开启" : "夜间模式已关闭")

        .fontSize(18)

        .fontColor(this.open ? Color.White : Color.Black)



Toggle({ type: ToggleType.Switch, isOn: this.open })

        .onChange((value: boolean) => {

this.open = value; // 状态变化同步到变量,自动刷新UI

        })

    }

    .width('100%')

    .height('100%')

    .backgroundColor(this.open ? Color.Black : Color.White)

    .padding(15)

  }

}

Toggle开关联动背景色示例运行效果图

三、掌握知识

除了布局和组件,还需要掌握这几个核心开发知识,才能实现完整可交互的功能:

1. @State 状态管理

 @State是ArkTS最基础的状态装饰器,被@State装饰的变量是‌响应式状态变量‌——当变量值发生改变时,所有用到这个变量的UI会自动刷新,这是ArkUI实现交互的核心基础。

只能在@Component装饰的组件内定义

支持所有基本类型(string/number/boolean等)和对象、数组

状态改变后UI自动更新,不需要手动操作DOM

代码示例:

@Entry

@Component

struct StateDemo {

// 定义响应式状态变量

@StateinputContent: string = "";

@StateswitchStatus: boolean = false;



build() {

Column({ space: 20 }) {

// 状态变量直接用在UI中,变量变化UI自动变

Text(`输入内容:${this.inputContent}`)

        .fontSize(18)



TextInput({ placeholder: "请输入内容", text: this.inputContent })

        .onChange((val) => {

// 修改状态变量,UI自动刷新

this.inputContent = val;

        })



Toggle({ type: ToggleType.Switch, isOn: this.switchStatus })

        .onChange((val) => {

this.switchStatus = val;

        })

    }

    .padding(15)

  }

}

在登录、注册、计算器这些需要动态更新界面的场景,都需要用@State来管理数据,这是ArkTS声明式开发最核心的思想——‌数据驱动视图‌。

2. 弹窗 AlertDialog

 AlertDialog是系统原生弹窗,一般用来给用户展示提示信息,或者让用户做确认操作,在操作完成(比如登录成功/失败、注册完成)后非常常用。

代码示例:

// 在按钮点击事件中弹出弹窗

import router from '@ohos.router';

@Entry
@Component
struct LoginPage{
  @State username:string=""
  @State password:string=""
  build(){
    Column({space:20}) {
      Text("这个是登录页面")
        .fontSize(25)
        .fontColor(0x77d441)
        .height(50)
      Image($r('app.media.img'))
        .width(120)
        .height(120)
        .borderRadius(60)
        .shadow({ radius: 50, color: Color.Red })

      Text("账号登录")
        .fontSize(30)
        .fontWeight(FontWeight.Bolder)

      Row() {
        Text("账号")
          .fontSize(26)
          .width("40%")
          .textAlign(TextAlign.Center)
        TextInput({ text: this.username })
          .width('60%')
          .height(50)
          .onChange((value: string) => {
            this.username = value
          })
      }

      Row() {
        Text("密码")
          .fontSize(26)
          .width("40%")
          .textAlign(TextAlign.Center)
        TextInput({ text: this.password })
          .width('60%')
          .height(50)
          .type(InputType.Password)
          .onChange((value: string) => {
            this.password = value
          })
      }

      Button("登录")
        .width('100%')
        .height(50)
        .fontSize(22)
        .onClick(() => {
          // if else 全部写在onClick内部,大括号匹配
          if (this.username == "admin" && this.password == "123456") {
            // 登录成功弹窗
            AlertDialog.show({
              title: "登录成功",
              message: "欢迎回来,admin",
              confirm: {
                value: "确定",
                action: () => {
                  console.log("用户点击确认");
                  // 弹窗确认后跳转到主页,传递用户名参数
                  router.pushUrl({
                    url: "pages/HomePage",
                    params: {
                      username: this.username
                    }
                  })
                }
              }
            })
          }else{
            // 登录失败弹窗
            AlertDialog.show({
              title: "登录失败",
              message: "账号或密码错误,请重新输入",
              confirm: {
                value: "确定",
                action: () => {
                  // 清空输入框
                  this.username = ""
                  this.password = ""
                }
              }
            })
          }
        })
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

登录结果弹窗运行效果图

3. 路由 router

 路由用来实现‌多页面跳转和参数传递‌,一个应用一般会包含多个页面,通过路由管理页面的跳转、回退和数据传递。

首先要导入路由模块:import router from '@ohos.router';

跳转:router.pushUrl({ url: 'pages/页面名', params: { 参数key: 参数值 } })

接收参数:在目标页面的onPageShow生命周期中,通过router.getParams()获取参数

所有需要跳转的页面,必须在项目根目录的main_pages.json中注册,否则无法跳转

代码示例:

// 1. 注册页点击提交后,跳转登录页并传递注册信息

import router from '@ohos.router';
@Entry
@Component
struct Resister{
  @State username:string=""
  @State password:string=""
  @State password2:string=""
  build(){
    Column({space:20}){
      Text("这个是注册页面")
        .fontSize(25)
        .fontColor(0x77d441)
      Image($r('app.media.img'))
        .width(120)
        .height(120)
        .borderRadius(60)
        .shadow({radius:50,color:Color.Red})
      Text("账号注册")
        .fontSize(30)
        .fontWeight(FontWeight.Bolder)
      Row(){
        Text("账号")
          .fontSize(26)
          .width("40%")
          .textAlign(TextAlign.Center)
        TextInput({text:this.username})
          .width('60%')
          .height(50)
          .onChange((value:string)=>{
            this.username = value
          })

      }
      Row(){
        Text("密码")
          .fontSize(26)
          .width("40%")
          .textAlign(TextAlign.Center)
        TextInput({text:this.password})
          .width('60%')
          .height(50)
          .type(InputType.Password)
          .onChange((value:string)=>{
            this.password = value
          })
      }
     Row(){
        Text("确认密码")
          .fontSize(24)
          .width("40%")
          .textAlign(TextAlign.Center)
       TextInput({text:this.password2})
         .width('60%')
         .height(50)
         .type(InputType.Password)
         .onChange((value:string)=>{
           this.password2 = value
         })
     }

      Button('注册')
        .width('100%')
        .height(50)
        .fontSize(20)
        .onClick(()=>{
          if ((this.username!="")&&(this.password!="")&&(this.password2!="")&&(this.password=this.password2)) {
            router.pushUrl({
              url:"pages/LoginPage"
            })
          }
          else {
            AlertDialog.show({
              title:"注册失败",
              message:`两次密码不一样或为空,${this.username}`
            })
          }
        })
      Text('已有账号,立即登录')
        .fontSize(22)
        .fontColor(0x1677ff)
        .onClick(()=>{
          router.pushUrl({
            url:"pages/LoginPage"
          })
        })

    }
    .width("100%")
    .height("100%")
  }
}

图片:

代码示例:

// 2. 登录页接收注册页传递的参数

import router from '@ohos.router';
@Entry
@Component
struct LoginPage{
  @State username:string=""
  @State password:string=""
  build(){
    Column({space:20}){
      Text("这个是登录页面")
        .fontSize(25)
        .fontColor(0x77d441)
        .height(50)
      Image($r('app.media.img'))
        .width(120)
        .height(120)
        .borderRadius(60)
        .shadow({radius:50,color:Color.Red})

      Text("账号登录")
        .fontSize(30)
        .fontWeight(FontWeight.Bolder)

      Row(){
        Text("账号")
          .fontSize(26)
          .width("40%")
          .textAlign(TextAlign.Center)
        TextInput({text:this.username})
          .width('60%')
          .height(50)
          .onChange((value:string)=>{
            this.username = value
          })

      }
      Row(){
        Text("密码")
          .fontSize(26)
          .width("40%")
          .textAlign(TextAlign.Center)
        TextInput({text:this.password})
          .width('60%')
          .height(50)
          .type(InputType.Password)
          .onChange((value:string)=>{
            this.password = value
          })
      }

      Button('登录')
        .width('45%')
        .height(50)
        .fontSize(20)
        .onClick(()=>{
          if ((this.username!="")&&(this.password!="")){
            router.pushUrl({
              url:"pages/HomePage",
              params:{
                username:this.username,
                password:this.password
              }
            })
          }
        })
      Text('没有账号,立即注册')
        .fontSize(22)
        .fontColor(0x1677ff)
        .onClick(()=>{
          router.pushUrl({
            url:"pages/Resister"
          })
        })

    }
    .width("100%")
    .height("100%")
  }
}

图片:

注意:‌ 必须在这里把所有页面路径添加到src数组中,路由才能正常跳转,例如:

json文件示例

{

"src":[

"pages/Index",

"pages/RegisterPage",

"pages/LoginPage"

]

}

页面跳转流程图

四、事件

事件是用户和应用交互的桥梁,ArkTS中最常用的两类事件是输入变化事件和点击事件:

1. onChange(() => { }) 变化事件

 当组件的值发生改变时触发,一般用于‌输入框输入内容变化‌、‌开关状态切换‌、‌滑块值变化‌这类场景,可以拿到最新的值,同步给@State变量,让UI自动更新。

代码示例:

// 场景1:TextInput输入内容变化

@Stateusername: string = '';

TextInput({text: this.username})

  .onChange((newValue: string) => {

// 输入内容改变,更新状态变量,UI自动刷新显示最新内容

this.username = newValue;

console.log("当前输入内容:" + this.username);

  })



// 场景2:Toggle状态变化

@StateswitchOpen: boolean = false;

Toggle({type: ToggleType.Switch, isOn: this.switchOpen})

  .onChange((newStatus: boolean) => {

// 开关状态改变,更新状态变量,UI中依赖这个状态的部分自动刷新

this.switchOpen = newStatus;

  })

图片示例:

图片

2. onClick(() => { }) 点击事件

 当用户点击组件时触发,是最常用的交互事件,几乎所有可点击的元素(按钮、文本、图片、卡片等)都可以绑定点击事件,点击后执行对应的业务逻辑:比如提交表单、跳转页面、计算结果、弹出弹窗等。

代码示例:

// 场景1:按钮点击提交登录

Button("登录")

  .onClick(() => {

// 点击后做验证、弹窗、跳转等逻辑

if (this.username.length > 0 && this.password.length > 0) {

this.doLogin();

    } else {

AlertDialog.show({title: "提示", message: "请输入账号密码", confirm: {value: "确定", action: () => {}}})

    }

  })



// 场景2:文本点击跳转注册页

Text("没有账号?去注册")

  .fontColor('#007dff')

  .onClick(() => {

    router.pushUrl({url: "pages/RegisterPage"});

  })

总结

一、布局规则

所有页面都遵循 ‌一个根布局,支持任意嵌套子布局‌ 的规则,不同场景选择对应布局:

做垂直排列的列表/表单 → 选Column

做水平排列的导航/按钮组 → 选Row

做自定义组件相对定位 → 选RelativeContainer

做元素堆叠/悬浮效果 → 选Stack

做流式自动换行的标签/网格 → 选Flex

二、常用组件

不同功能场景对应使用对应原生组件,开发效率更高:

场景需求

使用组件

首页Banner自动轮播 Swiper

播放本地/网络视频 Video

展示本地/网络图片 Image

展示静态文字 Text

表单输入内容 TextInput

用户点击交互 Button

表单多选一场景 Radio

开关切换/多选勾选 Toggle

三、核心开发知识

这三个知识点是实现完整交互功能的核心,必须掌握:

‌@State状态管理‌:被@State修饰的变量是响应式变量,变量改变UI自动刷新,是「数据驱动视图」的核心基础

‌弹窗提示‌:用AlertDialog.show()弹出系统原生弹窗,适合做操作结果提示、二次确认

‌页面路由‌:通过router.pushUrl()实现多页面跳转,还可以通过params传递参数,跳转前必须在main_pages.json注册所有页面

四、核心交互事件

这两个事件覆盖了绝大多数交互场景,语法固定非常好记:

‌onChange变化事件‌:输入框输入、开关状态变化时触发,用来把最新值同步给@State变量

‌onClick点击事件‌:按钮、卡片等可点击元素触发,用来写点击后的业务逻辑(提交表单、跳转、弹窗等)


 

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐