学习视频中的每日笔记

第一天总结

组件说明:

  一个页面可以理解成一个组件

页面构成:

  1.@Entery 或者 @preview

  2.@Componet

3.stcuct 组件的名称

{

                4.构建函数

                 build(){

                        注意点:

                        1-可以没有内容

                        2-有内容必须是一个容器组件

                 }

}

页面创建会在main-page.json5形成路由,有映射关系,如果删除页面建议删除对应的联系,否则报错(不要复制文件,不会自动帮我们创建路由)

组件构成:

  和页面差不多,可以没有@entry修饰符

  组件可以到处,在其他页面导入使用

开发页面:

  口诀:头顶天,脚踩地!(从上到下,从左到右,从外往里,从大到小)

  布局:线性布局(要么横着排列要么竖着排列)

  Row 横向排列  纵向居中 内容超出不会显示滚动条

  Column  垂直排列  横向居中  内容超出不会显示滚动条

  主轴:排列方向的轴

  可以设置主轴的对齐方式:justifyContent(FlexAlign.Center)可以起始位置  居中 结束位置  对齐

第二天总结

  堆叠布局(Z向盖楼)Stack内 后一个元素永远压在前一个元素上面,可以通过translate调整元素自身位置

Grid(这里{space : 10}  可以设置子组件之间的间距){ GridItem(){} }

.columnTamplate(‘1fr 1fr’)可以划分几列和比例 

.rowTamplate  划分几行和比例

.columnGap(10) 列间距

.rowGap 行间距

滚动需求:

scroller :Scroller =new Scroller()  //滑动控制器

bulid(this.scroller){

        //有且只有一个子组件

        //要想滚动  必须让内容大于scroll大小

        //默认纵向滚动,如果需要横向,需要手动设置

}

事件绑定:

给元素添加事件方法:onChange(内容改变时)  onSubmit(提交内容时) onClick(点击时)onFocus(聚焦) onBlur(失去焦点)

元素(组件){}.onchange(()=>{

        //做一些事
提示:1.轻提示(需要引入包,自动关闭)2.弹窗提示(需要引入包,自动关闭)3.弹窗提示(不需要引入包,点击关闭)

PromptAction.showToast({message:‘’})

PromptAction.showDialog({message:‘’})

AlertDialog.show({message:''})

})

第三天总结

关于函数:

        箭头函数:声明:()=>{}  没有自己的this ,this就是上级作用域的上下文

        组件内函数:声明:函数名(){  }

        调用:this.函数名() 看在哪里调用,谁调用的,this就指向谁(不确定,所以最好用箭头函数包裹,不要考虑改变this指向)

改变区域事件:

.onAreaChange((onldValue:Are,newVlaue:Area)=>{

onldValue.height//元素的大小宽高

}))

数据:

        声明数据:变量名:类型=默认值

        只会在第一次渲染页面时生效,后续更改数据不会引起页面更新

        @state修饰符修饰的数据,可以在改变后进行页面的更新

        简单数据类型(string,number,boolean)和引用数据类型自身及第一层变化时才生效

        如果是超出第一层的变化是监听不到的,解决方案:重新复制第一层对象即可!

重新创建对象可以new Class() -> class 可以通过interface 生成 (interface2Class)->只需要定义数据的结构,然后生成对应的类即可!

双向数据绑定:1.试图驱动数据(监听改变值的事件,更新数据)2.数据变化更新视图(@state)

优化:不需要在事件中手动改变值了,用$$添加在需要改变的值前面即可!

第四天总结

样式语法:

        1.样式分类:通用的样式+组件自带的

        2.样式的值:固定的值,或者枚举,让值变得有意义  

PX/VP/FP/LPX

PX 固定大小像素

VP虚拟像素 1VP=3PX

FP和VP一样  只不过改了系统字体,用fp的会变化(当前不支持只改字体)

lpx 类似于REM 可以设置屏幕基准值,然后给定值适配(老的项目迁移 或 单类型设备的开发)

Image

1.自建目录(assets)-> /aseets/a.png

2.用网络图片  Image('httpL//xxx')  模拟器和真机需要开网络权限

3.资源图片: media $r(‘app.media.a’)

4.rawfile: $r rawfile(a.png)

5.系统内置图标: $r(‘sys.media.icxxx’).fillColor(XX)  svg 是可以填充色的

6.下载SVG(icongont(阿里巴巴图标库)/华为官方图标库)

Color+String

先声明在使用

$r('app.media.color')

国际化:创建中英文俩个字段,切换语言时,文字会自动切换

@styles

function MyStyles(){

        1.不支持导入导出,只能在当前文件使用

        2.只支持通用样式

        3.不支持传参

}

@extend(Button)

function MyButtonStyles(可以传参){

        1.不支持导入导出,只能在当前文件使用

        2.只支持给某个组件添加,其他组件不能用

}

方法.styleStates

{

1.normal-> 初始状态:如果没有或者样式上不包含,出发其他状态就回不去了!

2.pressed->按压下的状态

3.disabled->禁用,会在原来的颜色上蒙层

4.focused->聚焦:预览器和模拟器tab切换才能出发

5.selected->选中下的样式,不常用

}

第五天总结

条件渲染:

if(){}else if(){} /else{}

visibility (Visbility.visiable)显示

Hidden 隐藏但是占位

Node 隐藏不占位

循环渲染:

ForEach(要循环的数据,(item:类型)=》{

        结构体

},()=》{返回唯一标识的字符串},宁愿不写,也不要乱写)

组件传值:

        进入页面/离开页面 aboutToApper()  aboutToDisapper() 

        定时器:setInterval  clearInterval  需要定义接收值 

        延时器:setTimeout ClearTimeout

第六天总结

Builder && BuilderParam

1.有没有状态更新?

有,不要用全局builder,没有,推荐用全局Builder

2.需不需要子组件更新?

需要就用$$接收

eg:

响应式条件:1.有@state 2.字面量对象传入

@state

FormData:类型={}

@Builder

MyBuilder($$:类型){

        TextInput(text :$$.data)

}

这个有点问题        TextInput(text :$$.xxx)  换成  $$this.data.xxx

BuildParam 类似于vue的插槽,只能子组件内使用

声明一个默认的结构体,可以利用builder赋默认值

调用子组件时传入对应的builder 可以替换默认的结构体

第七天总结

buildParam

@builder

content(){

}

Child({

        1.传输局

        list:this.list

        2.传结构

        content:this.content

})

如果只有一个buildparam 并且不需要参数,可以使用尾随闭包的写法

Chld({

        1.传数据

list:this.list

}){

this.content()

}

修饰符

@state prop Link provide Consume

数据传递方式:

父子单向:父变子变,字不会自己变  就用Prop   prop可以有默认值 也可以没有

父子双向:父变子变,子变父也变,就用Link Link 不能有默认值

后代通信:

        提供:Provide(起别名)

        接受:Consume(t提供的名字)

                接受的别名

                Watch('update')

                userName:string =''

        update(){

                this.userName???如何变化了

        }

自定义弹层@CustomDialog 设置Height:110%可以不留白

1.创建弹层

        类似组件

2.注册弹层

        controller :CustomDialogController = new CustonDialogController({

                builder:结构体,

                customStyle:是否使用自定义样式

})

第八天总结

1.函数组件(结构组件)-》自定义构建函数

2.状态组件-》comp

        组件-》自定义构建函数

                传值(调用函数的时候传递)

                 传结构(不存在,自定义构建函数就是最小单元值)

        组件-》组件        

                父子组件-》单向Prop-》自己可以改 不会同步父组件

                                    双向Link->不能有默认值,自己改父组件也会同步

                                    场景:如果父组件state 修饰的是一个数组对象,但是要把对象传递给子组件,子组件还得修改这个对象,需要用Observed 修饰对象的类,子组件ObjectLink 接收传递的对象,不能修改这个对象的地址,只能修改属性

                跨带组件-》双向

                                提供:Provide

                                接收:Consume

3.页面之间

4.UIAbility 执剑

5.线程之间

6.进程之间

7.应用之间

8.设备之间

第九天总结

LocalStorage

        页面级UI级存储状态 需要创建  注入可以在Ability 共享至各个页面 会有垃圾回收机制回收

AppStorage

        应用级存储状态  可以直接存 直接读取

        两种写法

        修饰符:@StorageLink @StorageProp 需要给默认值

        API:AppStorage.setOrCreat('key',value)   AppStorage.get('key',默认值)

PersistenStorage

        持久化应用关闭仍然存在 ,需要先声明,而且不能再Ability 使用 存储大小2KB 需要搭配                 AppStorage

preferences

        持久化:不需要声明,可以直接写入和读取。可以用头多个仓库,每个仓库可以有多个key,          每个key可以存8kb

        一般使用都是封装成工具类使用 参考项目代码

环境变量:了解  比如深色 暗色模式

权限

        向系统申请:internet

         向用户申请:

                1.moudle.jsons配置 name ,reason userScen{ ability:[] ,when:''}

                2.ability 申请 mannager=abilityUIXXXX manager.requestPermissionsFromUser([''])

网络请求

        http

                const req=http.creatHttp()

                const  res=req.request("http.xxxx")

                res.result 就是请求的结果  是一个字符串

三方库

        axios

                const result = axios.get<object.AxiosResponse<object,null>>('http.xxxxx')

                result 是包装后的数据  result.data是真实接口的数据

同步异步

        口诀:耗时任务加await 所在函数加async

页面跳转路由

  //pushUrl  和 replaceUrl()   replaceUrl会替换 上个page不会留在栈内
            router.pushUrl({
              url:'pages/day11/FullScreenDemo'
            },
              //是否单例 会在栈内唯一
              router.RouterMode.Single
            )

带参数跳转 这里是个对象

定义接受类型class

新page中获取

模块间跳转

包的分类

        hap 可以有ability  可以有页面 可以有组件  可以有组件

        hsp 共享包 可以实现按需打包

        har 静态资源包 - 可以实现资源共享

app 上架包

如果是性能优先 建议使用har包

如果是体积优先 建议使用hsp包

跟原来项目关联

 //跳转到其他包
            //路径写法  @bundle:包名/模块名/页面路径/ets
            router.pushUrl({
              url:'@bundle:com.example.heimaday11/library/ets/pages/Index'
            })

如果是ability包也一样关联 

页面跳转到ability包 :

.onClick(() => {
          let want: Want = {
            deviceId:'',
            bundleName: "com.example.heimaday11",
            moduleName: "feature",
            abilityName: "FeatureAbility",
            parameters: {
              id: 123456
            }
          };
          (getContext() as common.UIAbilityContext).startAbility(want)

        })

这里是有参数的所以需要接受

 在page接受使用

 

 做一个类似支付的需求

.onClick(async () => {
          let want: Want = {
            deviceId: '',
            bundleName: "com.example.heimaday11",
            moduleName: "feature",
            abilityName: "FeatureAbility",
            parameters: {
              id: Date.now()
            }
          };
          await (getContext() as common.UIAbilityContext).startAbilityForResult(want,
            (err: BusinessError, result: common.AbilityResult) => {
              console.log("zqf", JSON.stringify(result))
            })

        })
Button("支付成功").onClick(() => {

        //结束自己
        (getContext() as common.UIAbilityContext).terminateSelfWithResult({
          resultCode: 200,
          want: {
            deviceId: '',
            bundleName: "com.example.heimaday11",
            moduleName: "entry",
            abilityName: "EntryAbility",
            parameters: {
              payResult: true
            }
          }
        })

      } )

尽量不要用视频里的弹窗   加个耗时操作就可以了

.onClick(async () => {
          let want: Want = {
            deviceId: '',
            bundleName: "com.example.heimaday11",
            moduleName: "feature",
            abilityName: "FeatureAbility",
            parameters: {
              id: Date.now()
            }
          };
          await (getContext() as common.UIAbilityContext).startAbilityForResult(want,
            (err: BusinessError, result: common.AbilityResult) => {
                console.log("zqf","payResult  :"+result.want?.parameters?.payResult)
              //弹窗百分百出
              setTimeout(()=>{
                promptAction.showToast({
                  message:"payResult  :"+result.want?.parameters?.payResult
                })
              },1000)

            })
        })

跳转到其他应用

 Button('跳转其他应用')
        .onClick(() => {
          let want: Want = {
            deviceId: '',
            bundleName: "com.example.meituanapp",
            moduleName: "entry",
            abilityName: "EntryAbility",
          };
          (getContext() as common.UIAbilityContext).startAbility(want)
        })

生命周期

 //如果没有销毁只会执行一次
  aboutToAppear(): void {

  }
  //页面销毁
  aboutToDisappear(): void {

  }
  //@Entry修饰的页面多了3个周期
  onPageShow(): void {
    //页面展示的时候进行触发
    // eg:路由跳转返回 应用前台后台切换
  }

  onPageHide(): void {
  }
  onBackPress(): boolean | void {
    
  }

获取屏幕宽高

方法一:

 aboutToAppear(): void {
    this.screenWidth = px2vp(display.getDefaultDisplaySync().width)
  }

方法二:

底层布局

  .onAreaChange((_old, _new) => {
      this.screenWidth = _new.width as number
    })

手势

   //单条写法
            // .gesture(
            //   LongPressGesture.onAction(()=>{})
            //     .onActionEnd(()=>{})
            //     .onActionCancel(()=>{})
            // )
            //多条写法
            // https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-combined-gestures
          .gesture(GestureGroup(GestureMode.Parallel,
            LongPressGesture()
              .onAction(() => {
                this.isShow = true
              })
              .onActionEnd(() => {
                this.isShow = false

              }),
            PanGesture().onActionUpdate((event) => {
              if (event.fingerList[0].globalX < this.screenWidth / 2) {
                this.selectType = SelectType.LEFT
              } else {
                this.selectType = SelectType.RIGHT
              }
            }).onActionEnd(() => {
              this.selectType = SelectType.NONE
            }),
          ))

文件下载

import { request } from '@kit.BasicServicesKit'

@Entry
@Component
struct DownLoadDemo {
  imageUrl: string = 'https://ww1.sinaimg.cn/mw690/458a9af8gy1hwxa47lqi8j20u01t4tfw.jpg'
  @State newPath: string = ""

  build() {
    Column() {
      Image(this.imageUrl)
        .width(200)
        .aspectRatio(1)

      Button("下载").onClick(async (event: ClickEvent) => {
        let filePath: string = getContext().cacheDir + '/' + Date.now() + '.jpg'

        const task = await request.downloadFile(getContext(), {
          url: this.imageUrl,
          filePath: filePath
        })
        task.on('complete', () => {
          this.newPath = filePath
        })

      })
      if (this.newPath !== '') {
        Image('file://'+this.newPath)
          .width(200)
          .aspectRatio(1)
      }


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


 画板+保存沙箱

import { Data } from '../10MeiTuan/api/MyData'
import { fileIo } from '@kit.CoreFileKit'
import image from '@ohos.multimedia.image'
import buffer from '@ohos.buffer'

@Entry
@Component
struct HuaBanDemo {
  // 画笔   加入抗锯齿
  myPen: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true))
  //画布的宽高
  @State
  canvasWidth: number = 0
  @State
  canvasHeight: number = 0
  @State
  imagePath: string = ''

  build() {
    Column() {
      Canvas(this.myPen)
        .width('100%')
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //画笔配置
          this.myPen.lineWidth = 2
          this.myPen.strokeStyle = '#f00'
        })
        .onTouch((event: TouchEvent) => {
          if (event.type === TouchType.Down) {
            this.myPen.beginPath()
            this.myPen.moveTo(event.touches[0].x, event.touches[0].y)
          } else if (event.type === TouchType.Move) {
            this.myPen.lineTo(event.touches[0].x, event.touches[0].y)
            this.myPen.stroke()
          } else if (event.type === TouchType.Up) {
            this.myPen.closePath()
          }
        })
        .onAreaChange((_old, _new) => {
          this.canvasWidth = _new.width as number
          this.canvasHeight = _new.height as number
        })

      Button('清空画布')
        .onClick(() => {
          this.myPen.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
        })
      Button('保存').onClick((event: ClickEvent) => {
        //jpeg 黑底  jpg透明底
        // this.imagePath = this.myPen.toDataURL('image/jpg')

        //保存到沙箱
        let img = this.myPen.toDataURL('image/jpg')
        const filePath = getContext().tempDir + '/' + Date.now() + '.jpg'
        const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
        const base64Image = img.split(';base64,').pop()
        const imageBuffer = buffer.from(base64Image, 'base64')
        fileIo.writeSync(file.fd, imageBuffer.buffer)
        fileIo.closeSync(file)
        this.imagePath = 'file://' + filePath

      })
      if (this.imagePath) {
        Image(this.imagePath)
          .width('100%')
      }

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值