kuikly-reactive-observer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseKuikly 响应式更新与指令系统
Kuikly Reactive Update and Directive System
核心机制
Core Mechanism
attr {}注意:内部使用observable比较新旧值,相等时不触发更新。==
When reading reactive fields in the closure, the framework automatically collects dependencies; when the field value changes, the bound UI attributes are updated automatically. Just update the data, and the UI responds automatically.
attr {}Note:usesobservableinternally to compare old and new values, no update is triggered when values are equal.==
响应式字段声明
Reactive Field Declaration
在 (实现了 接口)或任何 子类中使用:
PagerPagerScopePagerScopekotlin
// 推荐:PagerScope 扩展函数
import com.tencent.kuikly.core.reactive.handler.observable
import com.tencent.kuikly.core.reactive.handler.observableList
import com.tencent.kuikly.core.reactive.handler.observableSet
var counter by observable(0) // 单值
var list by observableList<String>() // 响应式列表,配合 vfor
var tags by observableSet<String>() // 响应式集合Use in (which implements the interface) or any subclass of :
PagerPagerScopePagerScopekotlin
// Recommended: PagerScope extension function
import com.tencent.kuikly.core.reactive.handler.observable
import com.tencent.kuikly.core.reactive.handler.observableList
import com.tencent.kuikly.core.reactive.handler.observableSet
var counter by observable(0) // Single value
var list by observableList<String>() // Reactive list, used with vfor
var tags by observableSet<String>() // Reactive set绑定到 UI
Bind to UI
kotlin
var title by observable("Hello")
Text {
attr {
text(ctx.title) // 直接引用响应式字段,自动绑定
}
}
// 更新 ctx.title = "World" 后,Text 自动刷新kotlin
var title by observable("Hello")
Text {
attr {
text(ctx.title) // Directly reference the reactive field, automatic binding
}
}
// After updating ctx.title = "World", Text refreshes automatically指令系统
Directive System
循环指令:vfor / vforIndex
Loop Directives: vfor / vforIndex
kotlin
var list by observableList<String>()
// vfor:遍历 observableList,增删时自动增量更新
List {
attr { flex(1f) }
vfor({ ctx.list }) { item ->
Text { attr { text(item) } }
}
}
// vforIndex:额外提供 index 和 count
vforIndex({ ctx.list }) { item, index, count ->
View {
attr { backgroundColor(if (index % 2 == 0) Color.GRAY else Color.TRANSPARENT) }
Text { attr { text("$index: $item") } }
}
}必须传闭包,不是直接传值{ ctx.list }。ctx.list
kotlin
var list by observableList<String>()
// vfor: Traverse observableList, automatic incremental update when adding or deleting items
List {
attr { flex(1f) }
vfor({ ctx.list }) { item ->
Text { attr { text(item) } }
}
}
// vforIndex: Provides additional index and count
vforIndex({ ctx.list }) { item, index, count ->
View {
attr { backgroundColor(if (index % 2 == 0) Color.GRAY else Color.TRANSPARENT) }
Text { attr { text("$index: $item") } }
}
}Must pass a closure, not directly pass the value{ ctx.list }.ctx.list
循环指令:vforLazy(超大列表)
Loop Directive: vforLazy (Large Lists)
仅在 中使用(不含 PageList、WaterfallList),动态增删可见范围外的虚拟节点:
ListViewkotlin
List {
attr { flex(1f) }
vforLazy({ ctx.list }, maxLoadItem = 50) { item, index, count ->
Text { attr { text(item) } }
}
}| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| itemList | | — | 数据源闭包 |
| maxLoadItem | | 30 | 内存中最大虚拟节点数,建议为一屏可见数的 2~3 倍 |
| itemCreator | | — | 构建闭包 |
Only used in (excluding PageList, WaterfallList), dynamically adds or removes virtual nodes outside the visible range:
ListViewkotlin
List {
attr { flex(1f) }
vforLazy({ ctx.list }, maxLoadItem = 50) { item, index, count ->
Text { attr { text(item) } }
}
}| Parameter | Type | Default Value | Description |
|---|---|---|---|
| itemList | | — | Data source closure |
| maxLoadItem | | 30 | Maximum number of virtual nodes in memory, recommended to be 2~3 times the number of visible items on one screen |
| itemCreator | | — | Builder closure |
条件指令:vif / velseif / velse
Conditional Directives: vif / velseif / velse
kotlin
var state by observable(0)
View {
vif({ ctx.state == 1 }) {
Text { attr { text("状态1") } }
}
velseif({ ctx.state == 2 }) {
View { attr { size(100f, 100f); backgroundColor(Color.GREEN) } }
}
velse {
Text { attr { text("其他状态") } }
}
}/velseif必须紧跟velse或vif,中间不能插入其他组件。velseif
kotlin
var state by observable(0)
View {
vif({ ctx.state == 1 }) {
Text { attr { text("State 1") } }
}
velseif({ ctx.state == 2 }) {
View { attr { size(100f, 100f); backgroundColor(Color.GREEN) } }
}
velse {
Text { attr { text("Other States") } }
}
}/velseifmust immediately followvelseorvif, no other components can be inserted in between.velseif
绑定指令:vbind
Binding Directive: vbind
类似 语句,绑定值变化时移除所有子组件并重建:
whenkotlin
var state by observable(0)
View {
vbind({ ctx.state }) {
when (ctx.state) {
1 -> Text { attr { text("状态1") } }
2 -> View { attr { size(100f, 100f); backgroundColor(Color.GREEN) } }
}
}
}绑定值为vbind时不执行 creator 闭包。null
Similar to the statement, removes all child components and rebuilds them when the bound value changes:
whenkotlin
var state by observable(0)
View {
vbind({ ctx.state }) {
when (ctx.state) {
1 -> Text { attr { text("State 1") } }
2 -> View { attr { size(100f, 100f); backgroundColor(Color.GREEN) } }
}
}
}When the bound value ofisvbind, the creator closure is not executed.null
高效更新列表:diffUpdate
Efficient List Updates: diffUpdate
kotlin
// 基本用法(基于 Myers diff 算法,只增删变化的 Item)
list.diffUpdate(newData)
// 自定义比较(通过 id 判断是否同一元素)
userList.diffUpdate(newUsers) { old, new -> old.id == new.id }| 方式 | 行为 | 性能 |
|---|---|---|
| 销毁所有 Item → 重建 | 差 |
| 只增删变化的 Item | 优 |
kotlin
// Basic usage (based on Myers diff algorithm, only adds/deletes changed Items)
list.diffUpdate(newData)
// Custom comparison (judge if it's the same element via id)
userList.diffUpdate(newUsers) { old, new -> old.id == new.id }| Method | Behavior | Performance |
|---|---|---|
| Destroys all Items → Rebuilds | Poor |
| Only adds/deletes changed Items | Excellent |
常见错误与约束规则
Common Errors and Constraint Rules
详见以下参考文件:
- 常见错误:COMMON_MISTAKES.md — 响应式依赖断开、对象内部属性修改不触发更新、vfor 闭包传值而非传闭包、ViewBuilder 未 invoke 等 8 类典型错误
- 指令约束规则:DIRECTIVE_RULES.md — vfor 闭包必须且仅生成一个根节点、根节点不能是指令节点、vforLazy 仅限 ListView、velseif/velse 必须紧跟 vif、vforIndex 的 index/count 更新规则等
See the following reference documents:
- Common Errors: COMMON_MISTAKES.md — 8 typical errors including broken reactive dependencies, internal object property modifications not triggering updates, passing values instead of closures in vfor, ViewBuilder not being invoked, etc.
- Directive Constraint Rules: DIRECTIVE_RULES.md — Rules such as vfor closures must generate exactly one root node, root node cannot be a directive node, vforLazy is limited to ListView, velseif/velse must follow vif immediately, update rules for index/count in vforIndex, etc.