Hibop.github.io icon indicating copy to clipboard operation
Hibop.github.io copied to clipboard

ArkTs 学习

Open Hibop opened this issue 11 months ago • 0 comments

组件&页面

  • @Entry 表示该页面为一个独立的 Page,可通过 router进行跳转。
  • @Component 对该对象封装之后,即可进行页面渲染,并构建 数据->视图的更新

    @Component 与 React.Component、 Vue.defineComponent类似

  • build() 渲染函数 类似 React组件中 render()、vue中的 setup()

    build衍生出@Builder装饰器:可以提供 View 视图封装,放在Component外其实类似纯函数式组件 特别注意:function是指通过 function声明的函数,不包括**箭头函数(Arrow Function) **。这是因为装饰器需要装饰类,装饰函数存在提升问题

@Builder
function ItalicText(content: string) {
    Text(content).fontSize(14).fontStyle(FontStyle.Italic).margin({ bottom: 10 })
}

@Entry
@Component
struct Index {
    @State message: string = 'Hello World';

    @Builder
    SubTitle() {
        // 这里展示计数
        Text(`The message is "${this.message}", count=${this.clickCount}`)
            .margin({ bottom: 10 })
            .fontSize(12)
            .fontColor('#999')
    }

    build() {
        RelativeContainer() {
            Text(this.message)
                .id('HelloWorld')
                .fontSize(50)
                .fontWeight(FontWeight.Bold)
                .alignRules({
                    center: { anchor: '__container__', align: VerticalAlign.Center },
                    middle: { anchor: '__container__', align: HorizontalAlign.Center }
                })
              
            this.SubTitle()
        }
        .height('100%')
        .width('100%')
    }
}

核心API及装饰器

1、布局 in build

  • 线性布局: Row() Column() {}:单行布局
  • 层叠布局: Stack() 堆叠效果
  • 弹性布局: Flex() {}:flex布局
  • 栅格布局: GridRow() GridCol()
  • 列表、网格、轮播、选项卡: List Grid Swiper Tabs
  • Text()
  • 相对布局:RelativeContainer() {}

2、 样式相关装饰器

  • @Extend和 @Styles
  • 散养样式: 不推荐
@Extend(Text)
function TextStyle(fz: number = 50, fc: ResourceStr | Color = '#f00') {
    .fontSize(fz)
    .fontColor(fc)
    .fontWeight(FontWeight.Bold)
    .id('HelloWorld')
}


@Entry
@Component
struct Index {
    @State message: string = 'Hello World';
    
    // 声明Style簇
    @Styles
    HelloWorldStyle() {
        .backgroundColor(Color.Yellow)
        .border({ width: { bottom: 5 }, color: '#ccc' })
        .margin({ bottom: 10 })
    }

    build() {
        Flex({
            direction: FlexDirection.Column,
            justifyContent: FlexAlign.Center,
            alignItems: ItemAlign.Center,
        }) {
            Text(this.message)
                .id('HelloWorld')
                .fontSize(50)
                .fontWeight(FontWeight.Bold)
                .TextStyle()
                .HelloWorldStyle()  // !!! 注意这里调用样式簇 HelloWorldStyle
        }
        .height('100%')
        .width('100%')
    }
}

3、属性、状态 & 监听

mvx架构下:数据模型(model)一般分为 属性Prop和 状态State两种概念,都可以数据驱动视图(view)更新 这在var(vue angular react)框架都有所体现

  • @State:私有状态

  • @Prop:外部传入状态

  • @Watch 类似React.useEffect Vue.watch @Prop被第一次赋值的时候,不会触发 @Watch监听器, web的解决方案中,这种问题自然是绑定组件生命周期。onAttach() 中使用监听函数初始

  • @BuilderParam:实现slot插槽UI传递

    在向@BuilderParam插槽传入@Builder的时候,一定包一层箭头函数,否则会引起this指向问题。

    • 属性访问: this.state
    • 属性更新: this.state = new
    • 属性监听: @State @Watch('handlerFn') state
// 子组件@Cumstom
@Component
export struct CustomButton {
    onClickMyButton?: () => void
    @Prop text: string = 'My Button'
    @Prop @Watch('onChange') count: number = 0

    @State private double: number = 0

    @BuilderParam slot: () => void

    private onChange() {
        this.double = this.count * 2
    }

    build() {
        Column() {
            Button(`${this.text}(${this.count} x 2 = ${this.double})`)
                .onClick(() => {
                    if(typeof this.onClickMyButton === 'function') {
                        this.onClickMyButton()
                    }
                })
             // 植入插槽,位置自定
            if(typeof this.slot === 'function') {
                this.slot()
            }
        }
        // 这里绑定生命周期
        .onAttach(() => {
            this.onChange()
        })
    }
}


/// 父级调用方组件 
CustomButton({
    text: '点击次数',
    count: this.clickCount,
    onClickMyButton: () => {
        this.clickCount += 1
    },
    // 定义插槽  在向@BuilderParam插槽传入@Builder的时候,一定包一层箭头函数,否则会引起this指向问题。
    slot: () => {
        this.SubTitle()
    }
})

4、交互:事件回调

没有事件传递————没有 冒泡或 捕获过程 onClick()

5、异步

  • 首先:HTTP网络请求需要申请ohos.permission.INTERNET权限
// module.json5
"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET",
    "usedScene": {
      "when": "always"
    }
  }

  • 调用HTTP网络请求 @ohos.net.http 动态获取数据,进行UI列表刷新
import http from '@ohos.net.http';
import MyData from '../MyData'
 
export default async function getHttpData(url, data): Promise<MyData[]> {
  const dataList: MyData[] = []
  const baseUrl = 'https://mra-his.huawei.com/mra/rest/'
  const httpRequest = http.createHttp()
  const response = httpRequest.request(
    baseUrl + url, // 可以带参数也可以不带参数, 请求的参数可以在extraData中指定
    {
      method: http.RequestMethod.GET, // 可选,默认为http.RequestMethod.GET
      header: {
        'Content-Type': 'application/json'
      },
      expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型
    }
  )

  return await response.then((data) => {
    if (data.responseCode == 200) {
      // 处理返回结果
      const response = data.result
      const res = JSON.parse(response).data
      return res
    } else {
      // todo 请求失败,进行失败逻辑处理
    }
  }).catch((err) => {
    // todo 请求失败,进行失败逻辑处理
    console.info('error:' + JSON.stringify(err));
  })
}


@Component
struct Index {
  @State dataList: Array<MyData> = [{ id: "1", content: "content", createTime: "" }]
  
  async aboutToAppear() {
    this.dataList = await getHttpData('hello/world')
  }
}

Hibop avatar Jan 27 '25 03:01 Hibop