鸿蒙 Next 中 Link 的用法详解

一、@Link概述

在鸿蒙Next中,@Link装饰器用于在父子组件之间建立双向的数据同步关系。这意味着子组件中被@Link装饰的变量与其父组件中对应的数据源可以相互同步数据。从API version 9开始,该装饰器支持在ArkTS卡片中使用,从API version 11开始,支持在元服务中使用。

(一)同步机制

  1. 父组件中的数据源(如@State@StorageLink@Link)与子组件的@Link装饰变量之间实现双向数据同步。
  2. 任何一方数据的改变都会实时同步到另一方。

(二)限制条件

@Link装饰器不能在@Entry装饰的自定义组件中使用。

二、装饰器使用规则

  1. 参数:无参数。
  2. 同步类型:双向同步。
  3. 允许装饰的变量类型
    • Object、class、string、number、boolean、enum类型及其数组。
    • 支持Date类型。
    • API11及以上支持Map、Set类型。
    • 支持ArkUI框架定义的联合类型Length、ResourceStr、ResourceColor类型。
    • 类型必须被指定,且和双向绑定状态变量的类型相同。不支持any,API11及以上支持联合类型(如string | number、string | undefined或ClassA | null)。
    • 当使用undefined和null的时候,建议显式指定类型,遵循TypeScript类型校验。
  4. 被装饰变量的初始值:无,禁止本地初始化。

三、变量的传递/访问规则

  1. 从父组件初始化和更新
    • 必选,与父组件@State@StorageLink@Link建立双向绑定。
    • 允许父组件中@State@Link@Prop@Provide@Consume@ObjectLink@StorageLink@StorageProp@LocalStorageLink@LocalStorageProp装饰变量初始化子组件@Link。从API version 9开始,@Link子组件从父组件初始化@State的语法为Comp({ aLink: this.aState }),也支持Comp({aLink: $aState})。
  2. 用于初始化子组件:允许,可用于初始化常规变量、@State@Link@Prop@Provide
  3. 是否支持组件外访问:私有,只能在所属组件内访问。

四、观察变化和行为表现

(一)观察变化

  1. 基本类型(boolean、string、number):可以同步观察到数值的变化。
  2. class或Object类型:可以观察到赋值和属性赋值的变化(即Object.keys(observedObject)返回的所有属性)。
  3. 数组类型:可以观察到数组添加、删除、更新数组单元的变化。
  4. Date类型:可观察到Date整体的赋值,以及通过其接口更新属性的操作。
  5. Map类型(API11及以上):可观察到Map整体的赋值,以及通过其接口更新值的操作。
  6. Set类型(API11及以上):可观察到Set整体的赋值,以及通过其接口更新值的操作。

(二)框架行为

  1. 初始渲染
    • 执行父组件的build()函数创建子组件实例。
    • 必须指定父组件中的@State变量初始化子组件的@Link变量,二者保持同步。父组件的@State状态变量包装类传给子组件,子组件的@Link包装类注册自身指针给父组件的@State变量。
  2. 数据源更新(父组件到子组件)
    • 父组件@State变量变更后,遍历更新所有依赖它的系统组件和状态变量(如@Link包装类)。
    • 通知@Link包装类更新后,子组件中依赖@Link状态变量的系统组件也会更新,实现父组件对子组件的状态数据同步。
  3. @Link更新(子组件到父组件)
    • @Link更新后,调用父组件的@State包装类的set方法,将更新后的数值同步回父组件。
    • 子组件@Link和父组件@State分别遍历依赖的系统组件,进行对应的UI更新,实现子组件@Link同步回父组件@State

五、使用场景示例

(一)简单类型和类对象类型的@Link

父组件ShufflingContainer中的@State变量(简单类型yellowButtonProp和类对象类型greenButtonState)通过@Link与子组件GreenButtonYellowButton进行双向同步。在子组件中修改数据会同步到父组件,在父组件中修改数据也会同步到子组件。

(二)数组类型的@Link

父组件Parent@State数组arr通过@Link与子组件Childitems数组进行双向同步。子组件可以进行数组元素的添加、替换等操作并同步到父组件,父组件数组的变化也会同步到子组件。注意,@Link@State的数组类型必须相同,不能将@Link定义为单个元素类型去接收@State数组中的数据项(若有此需求可参考@Prop@Observed)。

(三)装饰Map类型变量(API11及以上)

子组件Child@Link变量value(类型为Map<number, string>)与父组件MapSample2@State变量message进行双向同步。在子组件中可以对Map进行各种操作(如初始化、设置新值、清除、替换和删除元素等),视图会随之刷新,并且操作会同步到父组件。

(四)装饰Set类型变量(API11及以上)

子组件Child@Link变量message(类型为Set<number>)与父组件SetSample1@State变量message进行双向同步。子组件对Set的操作(如初始化、添加元素、清除、删除元素等)会同步到父组件,父组件的变化也会同步到子组件,同时视图会相应刷新。

(五)使用双向同步机制更改本地其他变量

通过@Watch装饰器,在子组件Child@Link变量sourceNumber的变化时,可以修改本地@State变量memberMessage,实现父子组件间变量的同步,但本地修改memberMessage不会影响父组件中的变量。

(六)Link支持联合类型实例

父组件Index@State变量name(类型为string | undefined)通过@Link与子组件Childname变量进行双向同步。在父组件或子组件中改变name的属性或类型,另一方会对应刷新。

六、常见问题及解决方法

(一)@Link装饰状态变量类型错误

子组件中@Link装饰的变量必须与数据源类型完全相同,且数据源需为被@State等装饰器装饰的状态变量。例如,若数据源为@State装饰的ClassA类型变量,子组件中@Link也应声明为ClassA类型,而不是其属性的类型。

(二)使用a.b(this.object)形式调用,不会触发UI刷新

@Link装饰的变量是Object类型,且在build方法内通过a.b(this.object)形式调用时(如通过静态方法或组件内部方法修改Object属性),无法触发UI刷新。解决方法是先对变量进行赋值,使修改操作作用于带有Proxy代理的变量,从而实现UI刷新。

### 解决 Cursor 错误请求被阻止问题 当遇到 `cursor error` 并提示由于可疑活动而导致请求被阻止的情况时,通常是因为服务器检测到异常行为并采取了安全措施。以下是可能的原因以及解决方案: #### 可能原因分析 1. **IP 地址被列入黑名单** 如果客户端的 IP 被认为存在恶意行为,则可能会触发服务器的安全机制,从而导致请求被拒绝[^1]。 2. **频繁访问或超出速率限制** 过多的 API 请求可能导致服务器将其视为潜在威胁,并暂时封锁该连接[^2]。 3. **不合法的身份验证令牌** 使用过期或者伪造的身份验证令牌也可能引发此类错误消息[^3]。 4. **浏览器插件干扰** 某些广告拦截器或其他扩展程序可能会影响正常的网络通信过程,进而造成类似的错误现象[^4]。 5. **数据库游标超时设置不当** 对于某些应用而言,“cursor”指代的是数据库查询中的游标对象;如果长时间未操作而使得会话断开,则同样会出现上述状况[^5]。 #### 针对性解决办法 - **确认当前使用的 IP 是否正常** 尝试更换不同的网络环境重新发起尝试,观察是否有改善效果。 - **调整请求频率至合理范围之内** 查阅目标服务文档了解其允许的最大 QPS (Queries Per Second),据此优化自己的调用逻辑以满足规定条件。 - **更新认证凭证** 确认所依赖的所有授权信息均处于有效期内,并按照官方指南完成必要的刷新流程。 - **禁用第三方软件影响因素** 测试期间可以考虑临时关闭那些已安装但不确定作用的附加组件来排除它们带来的副作用。 - **适当延长 cursor 的存活周期** 根据实际需求修改相关参数配置文件里的 timeout 值,给予更充裕的时间窗口处理数据读取任务。 ```javascript // 示例代码展示如何通过 MongoDB 设置更大的批处理大小和增加生存时间 const MongoClient = require('mongodb').MongoClient; let client; async function main() { const uri = 'your_connection_string'; client = new MongoClient(uri, { useNewUrlParser: true }); await client.connect(); const collection = client.db("test").collection("accounts"); let cursor = collection.find().batchSize(10).noCursorTimeout(true); } main() .then(() => console.log("Operation completed")) .catch(err => console.error(`An error occurred while running the script: ${err}`)) .finally(() => client.close()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值