当前位置: 首页 > 知识库问答 >
问题:

harmonyos - 如何合理构造数据集合类和控件之间的相关联(详细请看描述)?

赏新知
2024-07-19

不使用@ObservedV2下

  • 在ViewModel中持有单个数据类DataClass和其成员变量name,在网络请求之后给这两个赋值(若DataClass有多个成员变量也一并添加在ViewModel中,请求过后赋值)

    @Observed
    class DataClass {
        name: string = ''
    }
    
    @Observed
    export class XxxViewModel {
        private _data: DataClass
        private _name: string = ''
    
        public set data(value: DataClass) {
            this._data = value
        }
    
        public get data(): DataClass {
            return this._data
        }
    
        public set name(value: string) {
            this._name = value
        }
    
        public get name(): string {
            return this._name
        }
    
    
        constructor() {
            this._data = new DataClass()
        }
    
        async getData() {
            let result: DataClass = await network()
            if (result) {
                this.data = result
                this.name = result.name
            }
        }
    }

    在Component中@State装饰ViewModel实例,每一个子组件关联ViewModel的一个属性类似于:

    @Entry
    @Component
    struct Index {
        @State viewModel: XxxViewModel = new XxxViewModel()
    
        aboutToAppear(): void {
            this.viewModel.getData()
        }
        build() {
            Row() {
                Column() {
                    Text(this.viewModel.name)
                }
            }
        }
    }
  • ViewModel只持有DataClass成员变量, 页面拆分出多个Component使用@ObjectLink修饰,观察
    DataClass的属性类似于:

    @Entry
    @Component
    struct Index {
        @State viewModel: XxxViewModel = new XxxViewModel()
        aboutToAppear(): void {
            this.viewModel.getData()
        }
        build() {
            Row() {
                Column() {
                    NameComponent({ dataClass: this.viewModel.data })
                }
            }
        }
    }
    
    @Component
    export struct NameComponent {
        @ObjectLink dataClass: DataClass
    
        build() {
            Text(this.dataClass.name)
        }
    }

    以上两种情况分别有不一样的问题:

  • 情况1: 如果和控件相关联的属性变多那么ViewModel中就需要添加更多的变量以及对其初始号
  • 情况2: 如果和控件相关联的属性变多那么页面需要新建更多的Component去观察变量变化

大家觉得有没有更好的解决方案呢?欢迎回答��

共有3个答案

慕容齐智
2024-07-19

ViewModel的扩张本就是UI增多导致的。这是自然而然的事情。
你当然可以继续拆分ViewModel为...ChildViewModel,类膨胀和字段膨胀你总得选一个

呼延宪
2024-07-19

目前没有好的方式,我这边做法和你的差不多

谢和颂
2024-07-19

在不使用特定框架(如@ObservedV2)提供的数据绑定和响应式编程功能时,合理构造数据集合类和控件之间的相关联确实是一个挑战。以下是一些可能的解决方案和考虑因素:

解决方案 1: 使用事件系统

ViewModel 不直接持有 UI 组件的状态,而是通过事件系统来通知 UI 组件状态的变化。

  • ViewModel:持有 DataClass 实例,并在数据变化时发布事件。
  • UI 组件:监听 ViewModel 发布的事件,并在事件处理程序中更新组件状态。

解决方案 2: 单一数据源

ViewModel 作为单一数据源,UI 组件通过 getter/setter 或直接访问 ViewModel 的属性来获取数据。

  • ViewModel:只持有 DataClass 实例,并提供 getter/setter 或直接访问属性。
  • UI 组件:在需要时从 ViewModel 获取数据,并在需要时(如 aboutToAppear)触发数据获取。

解决方案 3: 使用数据绑定库(如果有的话)

如果框架支持数据绑定库,即使不使用 @ObservedV2,也可以考虑使用这些库来简化数据绑定。

考虑因素

  • 可维护性:随着项目增长,保持代码的清晰和可维护性至关重要。
  • 性能:避免不必要的重新渲染和计算,特别是在处理大量数据或复杂 UI 时。
  • 解耦:保持 ViewModel 和 UI 组件之间的解耦,以便在需要时轻松更改或替换它们。

示例代码(基于解决方案 2)

这里是一个简化的示例代码,展示了如何使用单一数据源来关联 ViewModel 和 UI 组件:

class DataClass {
    name: string = ''
    // ... 其他属性
}

export class XxxViewModel {
    private _data: DataClass = new DataClass()

    public getData(): Promise<void> {
        return new Promise((resolve, reject) => {
            // 模拟异步网络请求
            setTimeout(() => {
                this._data.name = 'Loaded from network';
                resolve();
            }, 1000);
        });
    }

    public getDataClass(): DataClass {
        return this._data;
    }
}

@Entry
@Component
struct Index {
    private viewModel: XxxViewModel = new XxxViewModel()

    aboutToAppear(): void {
        this.viewModel.getData().then(() => {
            // 数据加载完成后的处理(如果有的话)
        });
    }

    build() {
        Row() {
            Column() {
                NameComponent({ dataClass: this.viewModel.getDataClass() })
            }
            // ... 其他组件
        }.width('100%')
    }
}

@Component
struct NameComponent {
    private dataClass: DataClass

    constructor(dataClass: DataClass) {
        this.dataClass = dataClass;
    }

    build() {
        Text(this.dataClass.name)
    }
}

请注意,这个示例代码是为了演示目的而简化的,并且可能需要根据实际项目需求进行调整。

 类似资料:
  • 这节课是数据类型篇最后一节了,这节课我们来讲下集合数据类型,集合这个数据类型很特殊,到底是个怎么特殊法,下面我们一起来看下: 1. 简介 1.1 定义 集合是一个无序、不重复的序列,集合中所有的元素放在 {} 中间,并用逗号分开,例如: {1, 2, 3},一个包含 3 个整数的列表 {‘a’, ‘b’, ‘c’},一个包含 3 个字符串的列表 1.2 集合与列表的区别 在 Python 中,集合

  • 问题内容: 在Java中,我不了解集合与“数据结构”。在我看来,集合是指列表,集合,映射,队列,而“数据结构”是指用于实现集合的数据结构,例如数组,链接列表或树。例如,ArrayList和LinkedList都是集合,但它们的数据结构分别是数组和链接列表。我是正确的,还是我在混淆条款? 问题答案: 数据结构是如何在内存中的存储器内部表示数据。集合是如何访问它的方法。我强调“可以”这个词。 如果将数

  • 本文向大家介绍Java从现有数据构造集合,包括了Java从现有数据构造集合的使用技巧和注意事项,需要的朋友参考一下 示例 标准馆藏 Java Collections框架 List从单个数据值构造a的一种简单方法是使用java.utils.Arraysmethod Arrays.asList: 所有标准集合的实现都提供了构造函数,该构造函数将另一个集合作为参数,在构造时将所有元素添加到新集合中: G

  • 问题内容: 作为学习的练习,我将在Swift中重写我的验证库。 我有一个协议定义了各个规则的外观: 关联的类型定义要验证的输入的类型(例如,字符串)。它可以是显式的或通用的。 这是两个规则: 在其他地方,我有一个函数,用于验证带有s 集合的输入: 我以为这行得通,但是编译器不同意。 在下面的例子中,即使输入是一个字符串,的是一个字符串,并且Ş 是一个String … …我收到了非常有用的错误消息:

  • 本文向大家介绍C++聚合关系类的构造函数的调用顺序详解,包括了C++聚合关系类的构造函数的调用顺序详解的使用技巧和注意事项,需要的朋友参考一下 如图,表示一个聚合关系 下面就用简单的代码来实现 由此可以看出,对象的构造函数调用的顺序就好像我们造车子一样,先打造好引擎和其他部件才能拼装好汽车,析构函数的调用就和拆开汽车一样,先扒开最外面的,然后再扒里面的。 以上这篇C++聚合关系类的构造函数的调用顺

  • 本文向大家介绍请详细描述AJAX的工作原理相关面试题,主要包含被问及请详细描述AJAX的工作原理时的应答技巧和注意事项,需要的朋友参考一下 AJAX是用于网页和服务器进行异步通信的技术。 基本原理是,通过XMLHttpRequest向服务器发送异步请求,获得服务器返回的数据,利用js更新页面。 其核心功能在于XMLHttpRequest对象。 创建一个ajax的步骤大致可以分为以下几步 创建XHM

  • 我已经找了一段时间了,但是找不到一个明确的答案。 很多人说使用联合来键入双关语是不明确的,也是不好的做法。这是为什么呢?我看不出它会做任何未定义的事情的任何理由,考虑到你写入原始信息的内存不会自动改变(除非它超出了堆栈的范围,但这不是一个联合问题,这将是一个糟糕的设计)。 人们引用严格的混淆现象规则,但在我看来,这就像说你做不到,因为你做不到。 此外,如果不打双关语,工会还有什么意义?我在某个地方

  • 我开始研究 OOAD,我很难找到一个 代码示例来说明如何以编程方式实现、和。(到处都有几篇文章,但它们与 C# 或 Java 有关)。我确实找到了一两个例子,但它们都与我的导师的指示相冲突,我很困惑。 我的理解是,在: < li >关联:Foo有一个指向Bar对象的指针作为数据成员 < li >聚合:Foo有一个指向Bar对象的指针,Bar的数据被深度复制到该指针中。 < li >组成:Foo有一