25

实施SegmentedControllIOSwith的最佳实践是ListView什么?我尝试了三种解决方案,所有示例都包含SegmentedControllIOS两个段和两个ListView. 我邀请您讨论这三个的性能(也许有人可以提出其他更好的解决方案)。从我的角度来看,示例是按照最有效的顺序给出的。

1.两个独立的dataSource,一个ListView(改变ListView的dataSource)

class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ds1: new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2,}),
      ds2: new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2,}),
      index: 0,
    };
  }

  render() {
    return (
      <View>
        <SegmentedControlIOS
          selectedIndex={this.state.index}
          values={['ds1', 'ds2']}
          onChange={() => this.setState({index: (this.state.index+1)%2})}
        />
        <ListView dataSource={this.state.index ? this.state.ds2 : this.state.ds1} />
      </View>
    );
  }
}

2.两个独立的dataSource和两个独立的ListView

class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ds1: new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2,}),
      ds2: new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2,}),
      index: 0,
    };
  }

  render() {
    return (
      <View>
        <SegmentedControlIOS
          selectedIndex={this.state.index}
          values={['ds1', 'ds2']}
          onChange={() => this.setState({index: (this.state.index+1)%2})}
        />
        {this.state.index === 0 ?
          (<ListView dataSource={this.state.ds1} />)
        :
          (<ListView dataSource={this.state.ds2} />)
        }
      </View>
    );
  }
}

3.一个dataSource,cloneWithRows on dataSource on change index

class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ds: new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2,}),
      ds1: ['some', 'data'],
      ds2: ['some', 'other', 'data'],
      index: 0,
    };
    this.onChange = this.onChange.bind(this);
  }

  onChange() {
    this.setState({
      ds: this.state.ds.cloneWithRows(this.state.index ? this.ds1 : this.ds2),
      index: (this.state.index+1)%2,
    })
  }

  render() {
    return (
      <View>
        <SegmentedControlIOS
          selectedIndex={this.state.index}
          values={['ds1', 'ds2']}
          onChange={this.onChange}
        />
        <ListView dataSource={this.state.ds} />
      </View>
    );
  }
}
4

2 回答 2

1

第三种方式最好。当您使用cloneWithRows' s函数来知道ListView它现在需要重新渲染哪些行时。由于在第一行会匹配,所以第一行不会被重新渲染。DataSourcerowHasChanged'some'ds1'some'ds2

如果您没有利用DataSource对象的状态 1,ListView则会看到它正在尝试呈现完全不同的(可能是不可比较的)数据源。

在案例 2 中,您可能会通过切换一个重量级的可滚动组件来获得一些有趣的渲染工件。

于 2016-10-29T09:02:37.203 回答
1

我认为这取决于用例

IMO,我会选择 opt2 开始,因为它简单且易于调试,如果有任何性能问题,我会选择 opt1(还要检查 FlatList 的实现方式:https ://reactnative.dev/docs/optimizing-flatlist-configuration )。我觉得 opt1 和 opt3 会导致 list1 渲染 list2 的数据,反之亦然

我认为,我们很少需要在第一次渲染大量行。通常,我们使用分页(或滚动到底部时连续加载),并且通过该加载,当您切换段时,数据会刷新并且您不必渲染大量行。

opt2 的优点是:

  • 易于理解的代码
  • 处理 renderRow 和 selectRow 也更容易,因为你有 2 个单独的列表。

有任何问题我可能会去 opt1,因为在 opt2 上,切换选项卡时会重新挂载整个列表,这不好(实际上,我们可以隐藏列表而不是卸载它,会消耗更多内存,但渲染速度更快)

而且性能仍然很差,我会考虑在原生端实现它:D

于 2021-05-29T10:28:53.353 回答