鸿蒙开发之状态管理@Prop和@Link

一、用法

在父子组件需要进行数据同步的时候,可以通过@Prop和@Link装饰器来做到。在父组件中用@State装饰,在自组件中用@Prop或@Link装饰。

结论:@Prop用于子组件只监听父组件的数据改变而改变,自己不对数据改变

           @Link用于子组件与父组件都会对数据改变,都需要在数据改变的时候发生相应的更新。

二、@Prop和@Link区别

2.1数据同步的类型不同

@Prop的数据是单向传递的,父组件改变能通知子组件,但是子组件改变不能通知父组件。

@Link的数据是双向传递的,父组件改变能通知子组件,子组件的改变也可以通知父组件。

2.2 装饰的变量类型不同

@Prop可以装饰的类型有限

  • 只能支持string、number、boolean、enum类型。
  • 如果父组件是对象类型,可以传递对象的属性,子组件可以内部可以是对象的属性。
  • 不可以是数组、any类型

@Link可以装饰的类型较多

  • 支持string、number、boolen、enum、object、数组等
  • 数组的增、删、改都可以触发更新
  • 嵌套类型以及数组中对象的属性无法触发更新,类似@State
2.3装饰后属性传递方式不同

@Prop装饰的属性不能初始化,因为传递方式是拷贝,从父组件中拷贝一份值给子组件。所以可以直接通过this.xxx传递。

@Link装饰的属性也不能初始化。传递方式是指针传递,需要用$修饰传递的属性。

三、实际案例

接上一篇state案例,我们在同一个组件中编写的代码,导致代码非常臃肿。那么,为了更加简洁,就对代码进行了拆分,将代码又拆分出来了2个组件TaskStitics(任务进度卡片)和StaticList(任务列表卡片)。

其中,TaskStitics组件只接收数据的改变,不会对数据改变,所以采用单向同步的@Prop装饰

StaticList组件因为可以对数据进行完成、删除等操作,也会对父组件的数据改变,所以采用双向同步的@Link装饰。


class Task {
  static  id: number = 1
  name:string = '任务名称'+Task.id++
  finished:boolean = false
}

@Styles function  card() {
  .width('90%')
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  .shadow({radius:6,color:'#1F00000',offsetX:2,offsetY:4})
}

@Extend(Text) function tasksuccessed(finish: boolean) {
  .decoration({type: finish ? TextDecorationType.LineThrough : TextDecorationType.None})
  .fontColor(finish? '#B1B2B1': Color.Black)
}


@Entry
@Component
struct  ProgressTask {

  @State totalTasks: number = 0
  @State finishTasks:number = 0
  @State tasks: Task[] = []
  
  build() {
    Column() {
      //顶部任务进度卡片
      TaskStitics({ totalTasks: this.totalTasks, finishTasks: this.finishTasks })
      //任务列表+新增按钮
      StaticList({totalTasks:$totalTasks,finishTasks:$finishTasks,tasks:$tasks})
    }
  }
}


@Component
struct TaskStitics {

  @Prop totalTasks: number
  @Prop finishTasks:number

  build() {
    //进度卡片
    Row() {
      Text('任务进度:')
        .fontWeight(FontWeight.Bold)
        .fontSize(30)
        .layoutWeight(1)

      Stack() {
        Progress({value:this.finishTasks,total:this.totalTasks,type:ProgressType.Ring})
          .width(100)

        Row() {
          Text(this.finishTasks.toString())
            .fontSize(24)
            .fontColor('#36D')

          Text(' / '+this.totalTasks.toString())
            .fontSize(24)
        }
      }

    }
    .card()
    .height(150)
    .margin({top:20,bottom:10})
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}

@Component
struct StaticList {

  @Link totalTasks: number
  @Link finishTasks:number
  @Link tasks: Task[]

  handleTaskNumber() {
    this.totalTasks = this.tasks.length
    this.finishTasks = this.tasks.filter(item =>
    item.finished
    ).length
    console.log('完成任务数'+this.finishTasks)
  }

  @Builder deleteButton(index:number) {
    Button('➖')
      .fontColor(Color.White)
      .backgroundColor(Color.Red)
      .width(40)
      .height(40)
      .type(ButtonType.Circle)
      .margin({left:5})
      .onClick(() => {
        this.tasks.splice(index,1)
        this.handleTaskNumber()
      })
  }

  build() {
    Column() {
      //添加按钮
      Button('新增任务')
        .width(200)
        .height(35)
        .onClick(() => {
          this.tasks.push(new Task())
          this.handleTaskNumber()
        })
        .margin({ bottom: 20 })

      //任务列表
      List({ space: 10 }) {
        ForEach(this.tasks, (task: Task, index) => {
          ListItem() {
            Row() {
              Text(task.name)
                .fontSize(20)
                .tasksuccessed(task.finished)

              Checkbox()
                .select(task.finished)
                .onChange(value => {
                  task.finished = value
                  console.log('任务状态' + value + '')
                  this.handleTaskNumber()
                })
            }
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          .swipeAction({ end: this.deleteButton(index) })
        }, item => '' + item.name)
      }
      .width('100%')
      .alignListItem(ListItemAlign.Center)
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
  }

}

四、补充@Provide和@Consume

@Provide和@Consume可以跨组件提供类似于@State和@Link的双向同步。

设想有三级组件父组件->子组件->孙子组件。

如果想要父组件与孙子组件中的数据达到双向同步,那么就需要先父组件与子组件绑定,然后子组件与孙子组件绑定,需要绑定多次。这个时候就可以用@Provide和@Consume装饰器了。

在父组件中用@Provide装饰,在孙子组件中采用@Consume装饰,就可以实现双向数据同步。

需要注意的是,使用这两个装饰器的时候不需要在父组件中传递参数。

整体关系如下图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/240391.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Skype的介绍及使用

介绍及使用说明 Windows自带的Skype是一款全球通用的即时通讯软件,它可以让用户通过文字、语音和视频进行免费的在线沟通。下面是Skype的使用说明: 1.安装和登录:如果你的Windows系统中没有预装Skype,你可以在Microsoft官…

锁定屏幕与挂起

概要: 本篇主要讲述Ubuntu22.04中的锁定屏幕和挂起 锁定屏幕就是大家通常所说的息屏、锁屏,英文单词是lock 挂起一般也被称为休眠、睡眠,英文单词是suspend 一、锁定屏幕 1、CtrlL 按下键盘上的CtrlL键,即可锁定屏幕&#x…

【华为鸿蒙系统学习】- HarmonyOS4.0开发工具和环境配置问题总结|自学篇

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 💫个人格言:"没有罗马,那就自己创造罗马~" 目录 官方链接 HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 安装教程 (…

【PTA刷题+代码+详解】求二叉树度为1的结点个数(递归法)

文章目录 题目C代码详解 题目 在二叉树T中,其度为1的结点是指某结点只有左孩子或只有右孩子。利用递归方法求二叉树T的度为1的结点个数。 1)如果TNULL,则是空树,度为1的结点个数为0,返回值为0; 2&#xff0…

Python爬虫实战 | 爬取拼多多商品的详情价格SKU数据

本案例将为大家演示如何爬取拼多多商品的详情数据。目的是爬取大量的商品以及商品的评论,所以在程序设计上要考虑到该爬虫的高并发以及持久化存储。爬虫工具选用了Scrapy框架,以满足爬虫的高并发请求任务;持久化存储用了MongoDB,对…

python:五种算法(SSA、WOA、GWO、PSO、GA)求解23个测试函数(python代码)

一、五种算法简介 1、麻雀搜索算法SSA 2、鲸鱼优化算法WOA 3、灰狼优化算法GWO 4、粒子群优化算法PSO 5、遗传算法GA 二、5种算法求解23个函数 (1)23个函数简介 参考文献: [1] Yao X, Liu Y, Lin G M. Evolutionary programming made…

vue 集成行政区域选择插件region和数据回显

故事:最近,项目需要进行行政区域围栏的绘制,由于老旧项目是利用js保存全国行政区域地址和编码,在选择器select进行匹配显示,但此方法复杂,因此选择集成区域插件region 步骤一:用命令安装region…

Vue3-09-条件渲染-v-show 的基本使用

v-show 的作用 v-show 可以根据条件表达式的值【展示】或【隐藏】html 元素。v-show 的特点 v-show 的实现方式是 控制 dom 元素的 css的 display的属性, 因此,无论该元素是否展示,该元素都会正常渲染在页面上, 当v-show 的 条件…

如何通过 SSH 访问 VirtualBox 的虚机

VirtualBox 是一款免费虚机软件。在用户使用它安装了 linux 以后,它默认只提供了控制台的管理画面。 直接使用控制台管理 Linux 没有使用诸如 putty 或者 vscode 这样的 ssh 远程管理工具方便。那么可不可以直接使用 ssh 访问 VirtualBox 上的 Linux 呢&#xff1f…

GNN 学习笔记

稍微看一下之后备用。 【图神经网络综述】GNN原理+落地应用实现框架全解_gnn实现-CSDN博客 GNN相比CNN最大的区别在于数据结构,CNN一般作用在二维、三维数据里,如图像、表格数据等,可以进行卷积操作。而GNN作用在一个由节点和边…

模拟目录管理 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C++ 题目描述 实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。 支持命令: 1)创建目录命令: mkdir 目录名称,如mkdir abc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作…

案例055:基于微信小程序的四六级词汇

文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…

超简单的新手重装Win10系统教程图解

如果我们的电脑系统出现问题了,那么就可以选择重装安装系统,轻轻松松解决系统问题,从而恢复对电脑的正常使用。但是,作为新手用户不懂很多的装机专业知识,所以重装系统的难度比较大,接下来小编给大家介绍超…

pytest-fixtured自动化测试详解

fixture的作用 1.同unittest的setup和teardown,作为测试前后的初始化设置。 fixture的使用 1.作为前置条件使用 2.fixture的的作用范围 1.作为前置条件使用 pytest.fixture() def a():return 3def test_b(a):assert a3 2.fixture的作用范围 首先实例化更高范围的fixture…

Javascript高频面试题

系列文章目录 文章目录 系列文章目录前言1.JavaScript常见数据类型null 和 undefind区别symbol(ES6新增)、bigInt(ES10新增) 2.JavaScript判断数据类型的方式3. 和 区别,分别在什么情况使用?4.变量声明 va…

Unity检测AssetBundle是否循环依赖

原理:bundle的依赖关系构建一个二维的矩阵图,如果对角线相互依赖(用1标记)则表示循环依赖。 using PlasticGui; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public cl…

Redis缓存异常问题,常用解决方案总结

前言 Redis缓存异常问题分别是:1.缓存雪崩。2.缓存预热。3.缓存穿透。4.缓存降级。5.缓存击穿,以 及对应Redis缓存异常问题解决方案。 1.缓存雪崩 1.1、什么是缓存雪崩 如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有…

zabbix6入门到精通(3) 预处理

zabbix6入门到精通(3) 预处理 配置 — 主机 文件系统主项目 vfs.fs.get 测试一下 添加预处理 $[?(.fsname ‘/’)] $[0].inodes.pfree JSONPath参照: https://www.zabbix.com/documentation/6.0/zh/manual/config/items/preprocessi…

【Docker】进阶之路:(十三)Docker Swarm

目录 Docker Swarm架构与概念 Docker Swarm架构 Docker Swarm 相关概念 1.Swarm 2.Node Docker Swarm是Docker官方提供的集群管理工具,它的主要作用是将Docker主机池转变为单个虚拟Docker主机,把若干台Docker主机抽象为一个整体,并且通过…

django实现增删改查分页接口

django实现增删改查分页接口(小白必备) 在上篇文章中我使用nodejs实现了增删改查分页接口,这一篇我们则使用django实现。 1.创建一个django项目,命令如下 python manage.py startapp myapp 2.在你自己的myapp文件夹中的models.py中定义你们自己的模型 f…