如何向ListView添加/删除项目?

31
我们可以像这样为ListView创建数据源。
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});  
var dataSource =  ds.cloneWithRows(['row 1', 'row 2']), };

但是,如果我想要从数据源中添加或删除项,我该怎么做?我需要始终使用更新后的数组调用cloneWithRows吗?

2个回答

64

是的,请调用cloneWithRows(...)

React Native文档没有涵盖ListViewDataSource对象,因此阅读源代码中的注释可以帮助理解其工作原理。

以下是一些有用的注释:

  • cloneWithRows(data) 的名称有点误导性,因为它并不像名字所示的那样只是创建数据的副本。

  • 相反,它会尝试将新的 data 行与数据源中现有行(如果有任何)进行比较,并确定是否有新行需要插入,或需要替换或删除的现有行。

  • 源代码注释指出,设计上数据源中的数据是不可变的,因此更改它的正确方法是指定更新后的数据源,即调用cloneWithRows(...)

传递整个列表来更改几行可能看起来不直观,但有几个原因使它合理:

  • 首先,这符合React的整体基于flux的架构,其中的重点是设置状态并允许组件自行确定如何变异以反映新状态(可以想象一下this.propsthis.state的工作原理)。您可以在ListView组件之外自由更改数据数组,但是一旦准备更新组件,则将整个状态传递给组件以使其自我更新是一个不错的flux方法。

  • 其次,它的效率相当不错。ListView在渲染过程中会进行重量级的行差异处理,并在渲染周期中一次只呈现一行(您可以调整此内容),以减少帧率下降。

  • 第三,这里没有排除未来支持像 .addRow(..) 这样的方法的可能性。关键是当前的实现并不是一个糟糕的开始,因为它提供了一个基于状态的接口,让开发人员不必担心列表组件在状态之间如何变化。


谢谢您的解释!我对这个名称感到非常困惑。您能更具体地说明如何更新一行中的某些信息吗? - Anh Nguyen
那么对于有成千上万行的列表呢?性能不会阻塞UI线程吗? - Oliver Dixon
谁会一次滚动10,000行? - sura2k

8

如果您查看React Native教程中的扩展电影示例,它实现了从远程API获取新电影的搜索。这意味着每次搜索都会刷新数据存储,有效地添加或删除项目。这种情况确切发生的地方在此处:

getDataSource: function(movies: Array<any>): ListView.DataSource {
    return this.state.dataSource.cloneWithRows(movies);
}

看起来你的方式是推荐的方法。

https://github.com/facebook/react-native/blob/master/Examples/Movies/SearchScreen.js#L209


哦,是的...看起来那似乎是唯一的方法!!但是应该有某种方式...因为这样我可能需要管理状态,例如滚动位置等... - thecodejack
好的观点,但您可以手动通过获取ListView的ScrollView滚动位置并在数据存储更新后设置它来完成。我同意这可能有点笨拙,如果您可以自动完成这个过程会更好。除非RN团队中有人能给出更好的答案,否则建议在Github跟踪器上开启一个问题。 - Colin Ramsay
其实公平地说,即使在完全本地化的iOS上,这似乎也是一个手动过程: https://dev59.com/vGMk5IYBdhLWcg3w7CKX#18855615 - Colin Ramsay
现在它更有意义了。无论如何,我更喜欢在此基础上构建一个包装器,以便RN在这种功能方面更加强大。我会在那里提出增强建议...让我们看看他们如何回应... - thecodejack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接