本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、基础概念
1. 核心定位
- 作用:在
@ComponentV2
组件中声明接收父组件传递的只读响应式参数 - 版本限制:仅支持
@ComponentV2
(传统@Component
需改用@Prop
) - 数据流方向:单向(父 → 子)
2. 与相关装饰器对比
装饰器 | 同步方向 | 可修改性 | 适用组件 | 类对象监听 |
---|---|---|---|---|
@Param | 父 → 子 | 只读 | @ComponentV2 | 仅整体赋值触发更新 |
@Link | 双向 | 可修改 | 全版本 | 深度监听属性变化 |
@Prop | 父 → 子 | 只读 | @Component | 深拷贝后独立更新 |
二、基础用法
1. 基本类型传参
// 子组件
@ComponentV2
struct Child {
@Param message: string = "默认值"
@Param @Require count: number // 必须传递
build() {
Text(`${this.message}, 计数: ${this.count}`)
}
}
// 父组件
@Entry
@ComponentV2
struct Parent {
@Local msg: string = "Hello"
@Local num: number = 42
build() {
Child({ message: this.msg, count: this.num })
}
}
2. 响应式更新机制
- 父组件修改
msg
/num
时,子组件自动更新 - 触发条件:父组件状态变量被重新赋值
三、类对象传参
1. 监听限制验证
class User {
name: string = "张三"
age: number = 25
}
// 子组件
@ComponentV2
struct UserCard {
@Param user: User
build() {
Text(`姓名: ${this.user.name}`)
}
}
// 父组件操作对比
Button('修改属性')
.onClick(() => {
this.user.name = "李四" // ❌ 子组件不更新
})
Button('整体替换')
.onClick(() => {
this.user = new User() // ✅ 子组件更新
})
2. 解决方案(3种)
方案1:不可变数据模式
// 父组件
updateUser() {
this.user = { ...this.user, name: "李四" } // 创建新对象
}
方案2:手动通知更新
class User {
// 添加更新方法
update(callback: () => void) {
callback() // 触发父组件重新赋值
}
}
// 使用示例
this.user.update(() => {
this.user = { ...this.user }
})
方案3:改用 @Link
(需双向绑定)
// 子组件
@ComponentV2
struct UserCard {
@Link user: User // 允许修改
}
// 父组件
UserCard({ user: $user }) // 使用$符号建立双向绑定
四、高级特性
1. 联合类型与可选参数
@ComponentV2
struct ConfigComponent {
@Param mode: 'light' | 'dark' = 'light'
@Param optionalTitle?: string
}
2. 参数校验
@ComponentV2
struct ValidComponent {
@Param @Require id: string
@Param score: number
aboutToAppear() {
if (this.score < 0) {
console.error("分数不能为负")
}
}
}
3. 性能优化建议
- 简单数据:优先使用基本类型
- 复杂对象:
- 需要属性监听 → 改用
@Link
- 只读场景 → 配合不可变模式使用
@Param
- 需要属性监听 → 改用
五、设计原理
- 性能优先:
@Param
的浅比较机制避免深度监听开销 - 明确数据流:强制单向传递防止副作用
- 类型安全:基于TS的编译时类型检查
"@Param
的响应式变化检测基于引用比对。对于复杂对象,建议将其视为不可变数据(immutable data),修改时创建新对象而非直接修改属性。"