React Native — хорошая практика: SegmentedControlIOS с ListView

#javascript #ios #listview #react-native #segmentedcontrol

#javascript #iOS #listview #react-native #segmentedcontrol

Вопрос:

Каковы наилучшие методы реализации SegmentedControllIOS ListView ? Я попробовал три решения, все примеры содержат SegmentedControllIOS два сегмента и два ListView . Я приглашаю вас обсудить производительность этих трех (возможно, кто-то может предложить другое, лучшее решение). С моей точки зрения, примеры приведены в порядке наиболее эффективного.

1. Два независимых источника данных, один ListView (измените источник данных 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})}
        />
        <ListView dataSource={this.state.index ? this.state.ds2 : this.state.ds1} />
      </View>
    );
  }
}
  

2. Два независимых источника данных и два независимых 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. Один источник данных, cloneWithRows для источника данных при изменении индекса

 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>
    );
  }
}
  

Ответ №1:

Третий способ будет лучшим. Когда вы cloneWithRows используете ListView функцию DataSource ‘s rowHasChanged , чтобы узнать, какие строки теперь необходимо повторно отобразить. Поскольку 'some' в первой строке ds1 будет совпадать 'some' в первой строке ds2 этой строки, она не будет повторно отображаться.

В случае 1 вы не используете состояние DataSource объекта, ListView он видит, что он пытается отобразить совершенно другой (возможно, несопоставимый) источник данных.

В случае 2 вы можете получить некоторые забавные артефакты рендеринга, отключив тяжелый прокручиваемый компонент.

Ответ №2:

Я думаю, это зависит от варианта использования

ИМО, я выберу opt2 для начала, потому что его просто и легко отлаживать, и opt1, если есть какие-либо проблемы с производительностью (также проверьте, как реализован FlatList: https://reactnative.dev/docs/optimizing-flatlist-configuration ). Я чувствую, что opt1 и opt3 могут привести к тому, что list1 отображает данные list2 и наоборот

Я думаю, нам редко нужно отображать большое количество строк в первый раз. Обычно мы используем подкачку (или непрерывную загрузку при прокрутке вниз), и при такой загрузке, когда вы переключаете сегмент, данные обновляются, и вам не нужно отображать большое количество строк.

Плюсы opt2 в том,:

  • легко понять код
  • обрабатывать renderRow и selectRow также проще, поскольку у вас есть 2 отдельных списка.

Я могу перейти к opt1 при возникновении каких-либо проблем, потому что в opt2 весь список повторно монтируется при переключении вкладки, что не очень хорошо (на самом деле, мы можем просто скрыть список вместо его размонтирования, это будет стоить больше памяти, но быстрее отрисовывается)

И производительность по-прежнему плохая, я подумаю о том, чтобы реализовать ее на родной стороне: D