返回博客首页
← 所有文章

ListView、RadListView 和 Repeater - 为什么需要三个?

2019年5月23日 — 作者:Martin Yankov

Repeater 是 NativeScript Core 框架中相关的组件。在 Angular 中,您有ngFor,在 Vue 中有v-for。虽然它们在实现上不完全相同,但它们的目的相同。

NativeScript 提供了三种创建数据绑定列表的官方方法。如果您来自 Web 开发背景并且不熟悉 NativeScript,这可能会让人感到困惑。当我第一次开始使用 NativeScript 时,这是我最困惑的两件事之一,另一件事是布局系统。

提示:查看nslayouts.com,轻松学习 NativeScript 布局系统!

在 Web 上,您希望有一种创建来自框架的数据列表的基本方法,然后有一系列捆绑了自定义功能的第三方插件。这是一个明确的区别 - 您使用基本实现并根据自己的喜好进行构建,或者选择其他开发人员构建的“更好”的实现之一。然而,在 NativeScript 中,有三个官方组件。这里有很多问题出现

使用哪个?哪个最好? überhaupt ein bestes? 为什么我需要三个?

目前,命名或文档中没有任何内容可以提供明确的答案。唯一弄清楚的方法是经验。如果您仔细检查组件的 API 并玩弄它们足够长的时间,您就会知道何时使用哪个。即使那样,也总是会存在疑问。这篇博文的目的是提供答案并将它们与实际示例结合起来。如果您不熟悉 NativeScript,它应该可以引导您朝着正确的方向前进。如果您已经很有经验,您至少可以确认您的理解(或您最深处的恐惧)。

在我们深入研究实际示例之前,我相信应该简要介绍一下这些组件。所有三个都有自己的文档,所以我认为我可能会提供一些替代方案。

ListView - 受人尊敬的绅士

这是一个简单而优雅的组件,可以让您创建您在杂志上看到的那些光滑的列表。其座右铭是“重质不重量”,它不关心那些尚未真正经受时间考验的新奇的实验性 UX 功能。它选择坚持经典并将其做好。诚然,这种设计决策导致它感觉有点过时,并将其从最佳 UX 的闪光中推开。虽然它不是最时尚的,但它仍然在每个移动应用程序中都占据着稳定的地位。当然,作为一个内心绅士,它仍然保持着高风亮节,所以如果您想扩展它(只要您有能力这样做),它会发挥很好的作用。这使其成为想要向其中添加一些花哨内容的第三方插件的良好基础。

ListView 是 NativeScript 核心模块(tns-core-modules 包)的一部分,这意味着它随框架开箱即用。在引擎盖下,它是基本原生列表控件(iOS 上的UITableView 和 Android 上的ListView)的薄包装器。其所有功能都来自原生实现。它非常快速且经过优化,因此如果您的应用程序主要针对低端设备,它是更好的选择。它具有三个功能

  • UI 虚拟化
  • 数据虚拟化
  • 多个模板

UI 虚拟化是此组件提供快速滚动的的原因。虚拟化是移动应用程序列表的事实标准。缺点是原生组件不提供关闭它的方法。这导致ListView必须处理自己的滚动,并且为了使其正常工作,必须为其提供明确的可用空间或大小。这意味着它在布局方面有一些特定的要求,这最终限制了它的设计选项。对于那些以列表为中心的页面来说,它是完美的组件,这些页面的大部分内容都充满了列表。

RadListView - 瑞士军刀小子

谁不喜欢一个能为您的每个问题提供解决方案的人?就像瑞士军刀一样,RadListView提供了您所有喜欢的功能以及更多功能。它甚至有一些功能,您无法说出它们的作用,但是当需要时,您会感谢它们。RadListView确实是三者中最酷的。它让您能够立即创建真正令人惊叹的列表体验。感觉就像魔法。遗憾的是,魔法是有代价的。你知道那句俗话,“样样通,样样松”,不幸的是,它也适用于RadListView,主要体现在性能方面。尽管如此,在当今时代,创造出色的体验往往胜过纯粹的效率。

RadListView是一个插件(nativescript-ui-listview 包),这意味着您必须在项目中单独安装它。在引擎盖下,它使用大量自定义代码构建在原生实现之上。如果ListView通过省略两个平台上都不存在的功能来提供跨平台 API,则RadListView方法是用自定义实现填补空白。结果是它提供了无数的功能,但也变得更加复杂且容易出错。与ListView一样,它提供了无法关闭的 UI 虚拟化,因此它在设计灵活性方面存在相同固有的问题。

列出RadListView可以执行的所有操作非常困难。它们范围从 UX 功能(如滑动操作和下拉刷新)到数据操作和模板。我建议查看文档和这篇博文。虽然博文有点过时,但它仍然非常相关。

值得注意的是,RadListView连同其余的专业 NativeScript UI 插件,不是开源的,但您可以签署 NDA 并获得访问权限并为其做出贡献。查看此处的说明,了解如何做到这一点。

Repeater - 辛勤工作的杰克

最终,总有人要完成工作。没有人真正喜欢谈论Repeater,因为我们都专注于用户体验,但我们只是害怕承认它实际上是每个应用程序的支柱。它专注于上面那些大人物不关心的不太重要的工作——可维护性。如果您需要重复多次的内容超过了您可以健康地复制粘贴的次数,那么Repeater就是您的组件。

Repeater附带tns-core-modules包,并且可能是其中唯一一个不包装原生 SDK 组件的组件。它实际上是 NativeScript Core 框架的一部分,其目的是提供 Angular 的*ngFor和 Vue 的v-for指令的等效项。这也意味着如果您使用其中一个框架,则不需要它。只需使用它们自己的实现即可。此外,此处提到的所有内容也适用于*ngForv-for

Repeater的主要优点是它是创建没有 UI 虚拟化且因此没有内部滚动的列表的唯一方法。这意味着您可以轻松地组合Repeater以实现更灵活的组合和设计。一个简单的经验法则是,如果您必须在同一页面上显示多个列表,那么Repeater可能是最佳解决方案。Repeater的缺点是它无法处理大型数据集。它没有虚拟化,因此它必须测量所有数据项模板,这需要时间。没有您可以使用的推荐项目的确切数量,因为它很大程度上取决于绑定和模板的复杂性。需要说明的是,如果您遇到Repeater的性能问题,您可能应该尝试使用ListViewRadListView

再说一遍,为什么是三个?

总而言之,NativeScript 提供了三个非常不同的组件,它们都有自己的个性

  • Repeater类似于 Angular 和 Vue 中的*ngForv-for,来自框架。它的主要优点是它没有虚拟化,可以安全地用于ScrollView中。Repeater 非常适合小型列表和组合列表。
  • ListView来自原生 SDK,是一个简单的包装器,提供跨平台 API。它的性能非常好。它在简单的经典场景中大放异彩。此外,更适合低端设备。
  • RadListView是一个使用大量自定义代码构建的插件。它提供了一组丰富的功能,很难自己实现。RadListView是为那些您希望拥有一个具有大量交互性的列表的场景而构建的。

所有三个都很重要,并且在移动应用程序中都有其位置。让我们观察一些实际示例。

示例

有时演示胜过千言万语。下面,您可以找到一些常见场景以及关于在哪些情况下哪个组件最合适的解释。请记住,此博客不是关于如何实现这些示例,因此没有详细的步骤。相反,我将提供指向 NativeScript Playground 中的示例的链接,您可以在其中部署并在您的设备上尝试它们。为简单起见,所有示例均使用 NativeScript Core 框架和 TypeScript 实现。

选择一项 - 使用 ListView

这就是最初制造移动设备的原因,还记得吗?从您的联系人列表中选择一个人并拨打电话。不需要花哨的干扰。这可能是您应用中的辅助或第三页。

Pick A Thing List GIF

这是一个经典的场景,其中ListView是完美的选择。RadListView在这里会有点矫枉过正,而且您无法控制数据集的大小,因此Repeater不是一个好选择。探索代码并在您的手机上查看它,方法是在 Playground 上访问此应用程序:选择一项 Playground 示例

简单的首页 - 使用 ListView 或 RadListView

让我们看看如何做类似于首页新闻提要的内容。

Simple Front Page ListView GIF

核心模块ListView在这里仍然是一个选项,我们可以从中受益于它的性能。它还提供了多个模板选项,因此我们可以通过为其提供不同的、更大的模板来提供特色新闻。还通过“加载更多项目”机制提供了数据虚拟化,因此如果用户向下滚动一点,我们可以获取更多新闻。这里没有真正需要交互。唯一缺少的是“下拉刷新”功能,您可以从单独的插件中获得它,例如下拉刷新插件来自Brad Martin。查看 Playground 中的示例:新闻提要 ListView Playground 示例

或者,您可以选择使用RadListView。根据您的模板布局,它的性能可能会稍差一些,但它内置了“下拉刷新”功能,如果您计划将来添加更多功能,它会容易得多。在这种情况下,这是一个选择问题。我建议使用RadListView,但请记住可能存在性能更好的选项。以下是在设备上的显示效果。它基本上是一样的,但请注意,这次我们开箱即用地拥有下拉刷新功能。

Simple Front Page RadListView GIF

以下是 Playground 中的示例:新闻提要 RadListView Playground 示例

交互式列表 - 使用 RadListView

假设我们想构建一个交互式的店面。我们希望客户能够在屏幕上看到尽可能多的商品,并且希望他们尽可能地停留在该屏幕上。

Storefront RadListView GIF

在这个例子中,我们结合了滑动操作、过滤和不同的布局以及不同的模板。这是RadListView的用武之地。使用其他两个列表也可以实现此功能,但会花费更多的时间和精力,最终性能可能也不会很好。这里捆绑了许多功能,因此请查看示例:店面 RadListView Playground 示例

应用菜单 - Repeater

应用菜单项通常在应用代码中定义,并且作为开发人员,您可以完全控制它们。它们通常数量不多 - 使用包含 1000 个项目的菜单并不友好。此外,菜单往往具有更华丽的设计,并且更常更改。

Menu Repeater GIF

此示例在顶部显示图标,下方显示应用菜单和个人资料菜单。使用Repeaters,我们可以将数据分成三个列表,分别放在三个Repeaters中,并将它们全部包装在一个ScrollView中。这是一个简单而灵活的解决方案。这里还有两个不同的分隔符,其中一个包含个人资料信息。相信我,使用ListViewRadListView实现这一点非常困难。请在此处查看示例:菜单 Playground 示例

结论

最初,拥有三种创建数据绑定列表的选项可能会让人感到困惑,但它们都有自己的优势和劣势。针对特定场景使用正确的选项可以节省开发时间并避免很多麻烦。我们可以根据以上示例提取一些简单的规则

  • 许多数据项 - 使用ListViewRadListView
  • 固定数量合理的数据项 - 使用Repeater
  • 交互式功能 - 使用RadListView
  • 单个屏幕上的多个大型列表 - 返回进行 UX 审查。

我希望这篇博文能帮助您走上正确的道路。如果您心中有一个此处未涵盖的场景,并且您不确定要使用哪个列表,请在下方发表评论。我很乐意与您讨论。