鸿蒙学习笔记

145 阅读3分钟

鸿蒙学习笔记

  • 基础组件的使用
  • 配置文件
  • 应用入口
  • 路由的使用
  • 组件中的数据同步
  • 网络请求
  • 本地数据保存

TypeScript

基础语法

let msg:string = 'hello world'
let age:number = 21
let finished:boolean = true
let a:any = 'jack'
a = 21

let u:string|number|boolean = 'rose'
u = 18

条件控制

let num:number = 21

if(num %2 === 0) {
console.log(num+'是偶数')
}
else {
console.log(num+"是奇数")
}



let grade:string = 'A'
swithc(grade) {
case 'A' {
console.log("优秀")
break
}
default {
console.log("一般")
break
}
}

循环

let names = ["J1","J2"]

for(let n of names){
    console.log("n:"+n)
}

函数

  • 默认参数
  • 空参数
  • 函数简写方式
function sayHello(name:string?):string {
    console.log("name:"+name)
    return name
}

function sayHello2(n?:string):string {
    let name = n ? n: "test1"
    console.log("name:"+name)
    return name
}


sayHello("test")

let sayHi = (name:string) => {
    console.log("hello,"+name)
}

sayHi("test")

面向对象


enum Msg {
    Hi = "hi",
    Hello = "Hello"
}

interface A {
    say(msg:Msg):void
}

class B implements A {
    say(msg:Msg) {
        console.log(msg+", I am B")

    }
}

let a:A = new B()
a.say(Msg.Hi)


例子2

class Rect {
    private w:number
    private h:number

    constructor(w:number,h:number){
        this.w = w
        this.h = h
    }

    public area():number {
        return this.w* this.h
    }
}

class Square extends Rect {
    constructor(s:number){
        super(s,s)
    }

}

let s = new Square(10)
console.log("area:"+s.area())

模块

  • export
  • import .. from 'file'
import {Header} from '../common/components/CommonComponents'
@Component
export struct Header{
  private title: ResourceStr
  @State params: any = router.getParams()
  build(){
    // 标题部分
    Row({space: 5}){
      Image($r('app.media.ic_public_back'))
        .width(30)
        .onClick(() => {
        })
      if(this.params && this.title){
        Text(this.params.id + '.' + this.title)
          .fontSize(28)
          .fontWeight(FontWeight.Bold)
      }
      Blank()
      Image($r('app.media.ic_public_refresh'))
        .width(30)
    }
    .width('98%')
    .height(30)
  }
}

组件使用

Image组件的使用

Image("https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/96c2cb5ead8247e09bf1a857982bc108~tplv-k3u1fbpfcp-watermark.image?")
  .width(100)
  .height(100)
Image($r('app.media.icon'))
  .width(200)
  .width(200)
  .padding(10)
  .interpolation(ImageInterpolation.High)

module.json5

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
],
  • 网络图片的显示
  • 本地图片的显示
  • 权限的设置

Text组件的使用

Text($r('app.string.width_label'))
  .fontSize(50)
  .fontWeight(FontWeight.Bold)
  // .fontColor(this.color)
  .onHover(()=> {
    this.message += 2
    // this.color = "#fff"
  })
  .onClick(()=> this.message += 1)
  • 资源的读取
  • 多语言的实现

布局的学习

  • 交叉轴
  • 主轴
  • margin
  • padding

image.png

循环控制

  • forEach
  • 可以多条重用

List

  • List
  • ListItem
  • 可以滑动
  List(){
    ForEach(this.items,(item:Item2)=>{
      ListItem() {
        Row() {
          Image($r('app.media.icon'))
            .width(98)
            .height(98)
              // .width(198)
            .padding(8)
            .interpolation(ImageInterpolation.High)
          Column(){
            Text(item.name)
            Text(item.price.toFixed(0))
              .padding({top:8})
          }
          .justifyContent(FlexAlign.Start)
          .alignItems(HorizontalAlign.Start)

        }
        .justifyContent(FlexAlign.Start)
        .backgroundColor("#fff")
        .width("90%")
        .height(118)
        .margin(14)
        .borderRadius(18)
        .padding(16)
      }
    }
    )
  }
}

自定义组件

  • export
  • import .. from ..
    • 可以增加重用
  • @Builder
    • 抽取代码,方便业务组件的重用
  • @Styles
    • 样式的抽取
    • 所有组件的公共样式
  • @Extend
    • 提取某个组件的样式
  • build函数中只允许有一个根
  @Styles fillScreen(){
  .width('100%')
  .height('100%')
  .backgroundColor('#EFEFEF')
  .padding(20)
}
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough})
  .fontColor('#B1B2B1')
}

@Builder function ItemCard2(item:Item2) {
  Row() {
    Image($r('app.media.icon'))
      .width(98)
      .height(98)
        // .width(198)
      .padding(8)
      .interpolation(ImageInterpolation.High)
    Column(){
      Text(item.name)
      Text(item.price.toFixed(0))
        .padding({top:8})
    }
    .justifyContent(FlexAlign.Start)
    .alignItems(HorizontalAlign.Start)

  }
  .justifyContent(FlexAlign.Start)
  .backgroundColor("#fff")
  .width("90%")
  .height(118)
  .margin(14)
  .borderRadius(18)
  .padding(16)
}

路由

  • router
    • 系统提供
  • 在main_pages.json中定义可用的page
  • 跳转时使用router.pushurl传入跳转的page来跳转
    • 可以传入url
    • 可以传入参数
    • 可以传入模式
  • 通过router.back来返回

import router from '@ohos.router'
import RouterInfo from '../viewmodel/RouterInfo'

@Component
export default struct RouterItem{
  r: RouterInfo
  i: number
  @Consume fontSize: number

  build(){
    Row(){
      Text(this.i + '.')
        .fontSize(this.fontSize)
        .fontColor(Color.White)
      Blank()
      Text(this.r.title)
        .fontSize(this.fontSize)
        .fontColor(Color.White)
    }
    .width('90%')
    .padding(12)
    .backgroundColor('#38f')
    .borderRadius(20)
    .shadow({radius: 6, color: '#4F000000', offsetX: 2, offsetY: 4})
    .onClick(() => {
      // router跳转
      router.pushUrl(
        {
          url: this.r.url,
          params: {id: this.i}
        },
        router.RouterMode.Single,
        err => {
          if(err){
            console.log(`路由失败,errCode: ${err.code} errMsg:${err.message}`)
          }
        }
      )
    })
  }
}

状态管理

  • @State
    • 通过这个来修饰变量以后就会绑定修改
    • 这个值变化会影响绑定的ui
    • 不能为空
    • 不支持any
    • 嵌套类型是不能触发变化
    • 数组变化是触发变化
    • 数组中的对象发生变化是不会触发变化v
  • @Entry
    • 页面的入口
  • @Prop
    • 单向同步
    • 不能初始化
    • 只支持基本类型
  • @Link
    • 双向同步
    • 不能初始化
    • 使用$来把地址传入进去
  • @Provider @Consume
    • 跨组件使用数据,使用@Provider在父组件标记对象
    • 在子组件使用@Consume标记的相同变量可以直接使用,不需要传递
    • 父组件和子组件名字必须相同
  • 函数传递
    • this数据的绑定
// 任务类
@Observed
class Task{
  static id: number = 1
  // 任务名称
  name: string = `任务${Task.id++}`
  // 任务状态:是否完成
  finished: boolean = false
}
// 任务统计信息
class StatInfo {
  totalTask: number = 0
  finishTask: number = 0
}

@Entry
@Component
struct PropPage {
  // 统计信息
  @Provide stat: StatInfo = new StatInfo()

  build() {
    Column({space: 10}){
      Header()

      // 1.任务进度卡片
      TaskStatistics()

      // 2.任务列表
      TaskList()
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F2F3')
  }
}


@Component
struct TaskStatistics {
  @Consume stat: StatInfo

  build() {
    Row(){
      Text('任务进度:')
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
      }
    }
    .card()
    .margin({top: 5, bottom: 10})
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}

@Component
struct TaskList {
  // 总任务数量
  @Consume stat: StatInfo
  // 任务数组
  @State tasks: Task[] = []

  handleTaskChange(){
    // 1.更新任务总数量
    this.stat.totalTask = this.tasks.length
    // 2.更新已完成任务数量
    this.stat.finishTask = this.tasks.filter(item => item.finished).length
  }

  build() {
    Column(){
      // 2.新增任务按钮
      Button('新增任务')
        .width(200)
        .margin({bottom: 10})
        .onClick(() => {
          // 1.新增任务数据
          this.tasks.push(new Task())
          // 2.更新任务总数量
          this.handleTaskChange()
        })

      // 3.任务列表
      List({space: 10}){
        ForEach(
          this.tasks,
          (item: Task, index) => {
            ListItem(){
              TaskItem({item: item, onTaskChange: this.handleTaskChange.bind(this)})
            }
            .swipeAction({end: this.DeleteButton(index)})
          }
        )
      }
      .width('100%')
      .layoutWeight(1)
      .alignListItem(ListItemAlign.Center)
    }
  }

  @Builder DeleteButton(index: number){
    Button(){
      Image($r('app.media.ic_public_delete_filled'))
        .fillColor(Color.White)
        .width(20)
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .backgroundColor(Color.Red)
    .margin(5)
    .onClick(() => {
      this.tasks.splice(index, 1)
      this.handleTaskChange()
    })
  }
}

@Component
struct TaskItem {
  @ObjectLink item: Task
  onTaskChange: () => void

  build() {
    Row(){
      if(this.item.finished){
        Text(this.item.name)
          .finishedTask()
      }else{
        Text(this.item.name)
      }
      Checkbox()
        .select(this.item.finished)
        .onChange(val => {
          // 1.更新当前任务状态
          this.item.finished = val
          // 2.更新已完成任务数量
          this.onTaskChange()
        })
    }
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

Stage模型

  • entry 入口
  • 模块分类
    • ability module
      • 可以有很多
      • 入口只能有一个 为entry,其他的为Feature
      • 打包为hap
    • library module
      • 打包为hsp

image.png

配置文件

  • app.json5
  • module.json5
  • mainpages.json5

生命周期

image.png

入口页面的配置

  • main_pages.json5
  • EntryAbility.ts
  • windowStage.loadContent image.png

页面的生命周期

  • aboutToAppear
  • aboutToDisappear
  • 页面生命周期
    • onPageShow
    • onBackPress
    • onPageHide
  • 页面生命周期在组件生命周期内不可用

image.png

  • 在一个page中启动另外一个Ability
    • 拿到content
    • 定义want
    • 使用startAbility启动
    • 在启动的Ability中重写onAcceptWant方法
    • 在module。json5中填写配置

使用网络库获取数据

  • viewModel中定义访问,使用的是http库
  • 在Model中定义对象
  • 得到的是Promise方法
  • 使用链式回调then和catch来处理返回值
  • 使用JSON.parse转化json为对象
  • 使用JSON.stringify把对象转为字符串
  • 在onEnd方法中处理分页,修改viewModel中的分页值,重新拉取
  • 数据合并
getShopListByHttp(): Promise<ShopInfo[]> {
  return new Promise((resolve, reject) => {
    // 1.创建http的请求对象
    let httpRequest = http.createHttp()
    // 2.发送请求
    httpRequest.request(
      `${this.baseURL}/shops?pageNo=${this.pageNo}&pageSize=3`,
      {
        method: http.RequestMethod.GET
      }
    )
      .then(resp => {
        if (resp.responseCode === 200) {
          // 查询成功
          console.log('testTag',  '查询商铺成功!', resp.result)
          resolve(JSON.parse(resp.result.toString()))
        } else {
          console.log('testTag',  '查询商铺信息失败!error:', JSON.stringify(resp))
          reject('查询商铺失败')
        }
      })
      .catch(error => {
        console.log('testTag',  '查询商铺信息失败!error:', JSON.stringify(error))
        reject('查询商铺失败')
      })
  })
}

使用第三方库来完成数据

  • 安装ohpm
  • ohpm/bin/init.bat
  • 使用ohpm.bat install @ohos/axio
  • ohpackage.json5
import axios from '@ohos/axios'
async getShopListByAxiosAsync(): Promise<ShopInfo[]> {
  // 1.发送请求
  let resp = await axios.get(
    `${this.baseURL}/shops`,
    {
      params: { pageNo: this.pageNo, pageSize: 3 }
    }
  )
  // 2.处理响应
  if (resp.status === 200) {
    // 查询成功
    console.log('testTag', '查询商铺成功!', JSON.stringify(resp.data))
    return resp.data;
  }
  // 查询失败
  console.log('testTag', '查询商铺信息失败!error:', JSON.stringify(resp))
}

数据保存

image.png

  • async
  • await
  • 异步转成同步

关系型数据库

  • 导入relationalStore
  • 拿到relationalStore对象
  • 拿到配置,生成relationalStore对象,拿到数据库链接
  • 拿到rdbStore以后,就可以执行executeSql了
  • 查询

image.png

查询

image.png

通知

  • 引入通知类
  • 创建通知请求
  • 发布通知
  • 取消通知

image.png