antd-mobile ListView 長列表 的數據更新遇到的坑

遇到的問題

listView這個組件我真的是看文檔看得腦袋疼。好不容易看文檔寫完長列表數據展現了。而後遇到一個需求,即用戶有一個點贊操做,問題出現了,點贊完數據更新以後listView不刷新列表。git

解決列表不刷新問題

官方的demo裏有這麼一個函數 rowHasChanged ,這個函數返回true或者false,若是是true,則認爲這行數據改變了,而後刷新這行數據,也就更新了列表。github

// 官方
 constructor(props) {
    super(props);
    ...
    const dataSource = new ListView.DataSource({
      ...
      rowHasChanged: (row1, row2) => row1 !== row2  // 這個方法
    });
  }

而後就各類百度,最後在github上看到這個 issue。最後你們得出的結論就是若是要繼續用這個組件,又想刷新列表的話就只能寫成下面這樣。
but,這樣寫會讓全部的數據都更新,對性能的消耗挺大的。後端

// !!!這樣寫
rowHasChanged: ( row1, row2) => true

emmm,可是我不想去看其餘的插件了,因此就採用了上面的寫法。antd

下面就講一下我怎麼配置這個listView的,由於我以爲這個組件官方demo還真的寫得蠻看不懂的。ide

ListView在實際項目中使用

下面的代碼主要展現怎麼配置listview,不要扣小地方,由於我把不少業務代碼去掉了。函數

class Message extends React.Component {
  constructor(props) {
    super(props);
    const dataSource = new ListView.DataSource({
    // 這樣寫,每次都執行rowHasChanged,每次都更新row
      rowHasChanged: ( row1, row2) => true
    });

    this.state = {
      dataSource,
    };
  }

  componentDidMount() {
    // 請求初始化數據
  }

  // 在這裏維護長列表數據,把從接口獲取來的數據賦值給state裏的dataSource。
  componentWillReceiveProps(nextProps) {
    if(nextProps.message.commentList !== this.props.message.commentList){
      this.setState({
      // 注意!這裏的cloneWithRows(),antd裏規定用它來更新dataSource,這個不是拼接數據,用這個函數,dataSource會更新成nextProps.message.commentList。
      //因此在接受後端分頁數據時,就把拼接好的數據賦值給nextProps.message.commentList(這個在model.js裏寫了)
        dataSource: this.state.dataSource.cloneWithRows(nextProps.message.commentList),
      });
    }
  }

// onEndReached,列表被滾動到距離最底部不足`onEndReachedThreshold`個像素的距離時調用
// 在這裏寫分頁請求
  onEndReached = (event) => {
    const { dispatch } = this.props;
    const { email } = this.props.user;
    const { pageNum, pageSize, contentId, totalCount, commentList } = this.props.message;
    
    let hasMore = totalCount > commentList.length ? true : false;
    // load new data
    // hasMore: from backend data, indicates whether it is the last page, here is false
    if (!hasMore) {
      return;
    }
    dispatch({
      type: "message/updateStates",
      payload: {
        pageNum: pageNum+1,
        isLoading: true,
        isLongList: true
      }
    })
    setTimeout(() => {
      dispatch({
        type: "message/getCommentsByContentId",
        payload: {
          contentId,
          identity: email, 
          pageNum: pageNum+1,
          pageSize
        }
      })
    }, 1000);
  }

  render() {
  // 列表的item
    const row = (rowData, sectionID, rowID) => {
      const item = rowData;
      return (
        <div className={styles.item} key={rowID}>
            <div onClick={toggleLike}>點贊</div>
            <div className={styles.content}>{item.content}</div>
            </div>
        </div>
      );
    };

    return (
      <Fragment>
          <ListView
          ref={el => this.lv = el}
          dataSource={this.state.dataSource}
          renderHeader={() => (
            <div className={styles.sub}>
              <span>列表頭,什麼寫點什麼</span>
            </div>
          )}
          renderFooter={() => (<div style={{ padding: 10, textAlign: 'center' }}>
            { isLoading ? '加載中' : '加載完畢'}
          </div>)}
          renderRow={row}
          className="am-list"
          pageSize={pageSize}
          useBodyScroll
          scrollRenderAheadDistance={500}
          onEndReached={this.onEndReached}
          onEndReachedThreshold={10}
        />
      </Fragment>
    );
  }
}

model.js性能

*getCommentsByContentId({ payload }, { call, put, select }) {
      const { data } = yield call(getCommentsByContentId, payload);
      const { message } = yield select(state=>state);
      const { commentList } = message;
      if (data.code === 200) {
        // 長列表,上一次頁的數據+此次的數據,賦值給新的commentList
        let list = [...commentList, ...data.data.list]
        yield put({
          type: 'updateStates',
          payload: {
            totalCount: data.data.totalCount,
            commentList: list
          }
        });
      } else {
        Toast.fail(data.msg, 1)
      }
    },
相關文章
相關標籤/搜索