react-native:ListView,如何从顶部推送新行

Posted

技术标签:

【中文标题】react-native:ListView,如何从顶部推送新行【英文标题】:react-native: ListView, how to push new rows from top 【发布时间】:2015-08-02 17:10:10 【问题描述】:

我一直在尝试了解如何制作一个可以经常接收新数据并将其推送到前面的 ListView。使用下面的代码,列表没有正确反映更改,而不是在顶部有一个新行,最后一个被重复了..

'use strict';

var React = require('react-native');
var 
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ListView,
  TouchableHighlight,
 = React;

var listview = React.createClass(
  rows: [],

  _rowHasChanged: function (r1, r2) 
    // if (r1 !== r2)
    //   console.log('rowChanged', r1, r2);
    // else
    //   console.log('row didn\'t Changed', r1, r2);
    return r1 !== r2;
  ,

  getInitialState: function() 
    return 
      dataSource: new ListView.DataSource(rowHasChanged: this._rowHasChanged),
    ;
  ,

  componentDidMount: function () 
    this.rows = [
      id: 0, text: '0: text',
      id: 1, text: '1: text',
      id: 2, text: '2: text',
      id: 3, text: '3: text',
    ];

    this.setState(
      dataSource: this.state.dataSource.cloneWithRows(this.rows),
    );
  ,

  pushTopRow: function () 
    var id = this.rows.length;
    this.rows.unshift(id: id, text: id + ': text');

    this.setState(
      dataSource: this.state.dataSource.cloneWithRows(this.rows),
    );
  ,

  render: function() 
    return (
      <View style=styles.container>
        <ListView
          dataSource=this.state.dataSource
          renderRow=(rowData) => <Text key=rowData.id>rowData.text</Text>
        />
        <TouchableHighlight
          onPress=this.pushTopRow>
          <Text>PUSH TOP</Text>
        </TouchableHighlight>
      </View>
    );
  ,
);

var styles = StyleSheet.create(
  container: 
    flex: 1,
    backgroundColor: 'orange',
  ,
);

AppRegistry.registerComponent('listview', () => listview);

然后我尝试了:

pushTopRow: function () 
    var id = this.rows.length;
    var newRow = [id: id, text: id + ': text'];
    this.rows = newRow.concat(this.rows);

    this.setState(
      dataSource: this.state.dataSource.cloneWithRows(this.rows),
    );
  ,

这确实有效,但我不明白为什么第一种方法不起作用。我试图弄清楚使用 ListView 处理的最佳做法是什么:

我是否应该在任何情况下都将 cloneWithRows 与一个新数组一起使用,即使 对于单个添加/删除操作? 是否有任何其他设置可以让 ListView/DataSource 机制在最少重绘的情况下正常工作(键、hasRowChanged 具体比较?),

有点缺乏文档和示例,为我和任何人澄清它会很棒。谢谢你,祝你代码日愉快。

【问题讨论】:

好的,我知道对更改差异进行了参考检查,因此不能简单地改变数组。 但我仍然不知道列表如何在不破坏所有布局的情况下知道位置变化,例如预先添加新元素或删除现有元素。 目前,行检查基于它是数组索引,当移动时,即使完全相同的元素只是下面的一行,它也会被认为是一个完全不同的值,因此会重新绘制。这对性能来说是灾难性的:/ 这可能只是为我节省了 4 或 5 个小时。非常感谢!!! 在我使用你的解决方案之前浪费了 1 小时......也谢谢你 我正在寻找相同的解决方案。如果有的话,请分享。 【参考方案1】:

ListView 通过数据源索引分配组件键,因此,只要数据源被添加到,就会重新呈现所有行。如果您的行数据有任何唯一的 id,您可以创建一个修改后的 ListView 使用它作为键。参见例如PrependableListView,它将在您的行数据上使用 id 属性。

注意:这个组件不是通用的,如果没有定义 id 属性会失败。

注意:我意识到这并不能回答您的全部问题,只是关于预先添加到数据源的特定特殊性。

【讨论】:

以上是关于react-native:ListView,如何从顶部推送新行的主要内容,如果未能解决你的问题,请参考以下文章

ListView 部分数据(react-native)

React-Native ListView加载图片淡入淡出效果的组件

带有导航的 React-native ListView

React-native 和 Firebase ListView 集成

React-Native组件之ListView

react-native ListView 封装 实现 下拉刷新/上拉加载更多