react native基于sectionlist實(shí)現(xiàn)類似通訊錄功能

效果圖:


exampleImage.png

最近自己研究了下react native里的sectionlist組件,寫了一個(gè)類似通訊錄功能的三方庫組件react-native-sectionlist-contacts,包含了點(diǎn)擊右邊的索引進(jìn)行對(duì)應(yīng)的跳轉(zhuǎn),下面就闡述下這個(gè)組件的原理和使用步驟以及當(dāng)中遇到的問題。

代碼原理

根據(jù)react native的sectionlist文檔,需要傳入一個(gè)數(shù)組類型的數(shù)據(jù)源給sectionlist,不過在此之前,需要定義下你所需要的頭部數(shù)據(jù)有哪些,我這里定下了26個(gè)字母加上一個(gè)默認(rèn)其他,具體代碼如下:

constructor(props) {
        super(props);
       //name字段必須,其他可有可無
        let nameData=[
            {name:'阿瑪尼',id:'amani',params: ''},
            {name:'OK',id:'ok',params: '123'},
            {name:'天津飯'},
            {name:'%……&'},
            {name:'周星馳'},
            {name:'習(xí)大表哥'},
            {name:'不要這樣'},
            {name:'V字仇殺隊(duì)'},
            {name:'拼車'},
            {name:'他媽跌'},
            {name:'淫僧'},
            {name:'錢學(xué)森'},
            {name:'寧采臣'},
            {name:'史泰龍'},
            {name:'恐龍'},
            {name:'任達(dá)華'},
            {name:'媽咪寶貝'},
            {name:'ing'},
            {name:'康麥隆'},
            {name:'劉德華'},
            {name:'精忠報(bào)國'},
            {name:'黃藥師'},
            {name:'大叔皮'},
            {name:'布達(dá)拉宮'},
            {name:'方世玉'},
            {name:'ET外星人'},
            {name:'程咬金'},
            {name:'**&&&&'},
        ]
        this.state = {
            dataArray: data,
        }
    }

然后通過查找資料,找到一個(gè)獲取首字母的方法,傳入一個(gè)字符串,不管是中文還是英文甚至火星文,都能獲取到他的首個(gè)字母,因?yàn)榇a比較多,所以還請(qǐng)?jiān)?a target="_blank">這個(gè)鏈接里查詢方法文件(getFirstAlphabet.js),之后再render方法里進(jìn)行渲染:

<SectionList
     {...this.props}
     style={this.props.SectionListStyle}
     ref={s=>this.sectionList=s}
     keyExtractor={this._keyExtractor}
     sections={delData}
     renderSectionHeader={this._renderSectionHeader}
     renderItem={this._renderItem}
     getItemLayout={(data, index) => ( {length: this.props.sectionHeight, offset: this.props.sectionHeight * index, index} )}
 />

delData是數(shù)組數(shù)據(jù)源,getItemLayout是給出一個(gè)預(yù)計(jì)算,如果能知道每個(gè)item的高度的情況下,設(shè)置對(duì)應(yīng)的值為此高度,能夠很好的提高組件的渲染效果,同時(shí)也是后面能夠點(diǎn)擊索引定位到位置所必須的條件。這里的sectionHeight就是每個(gè)item的高度。
當(dāng)然此組件也支持自定義頭部樣式和自定義內(nèi)容item樣式,可在文檔里看到,這里不做說明。
最后就是右邊索引的功能實(shí)現(xiàn),我這里做的是給出的數(shù)據(jù)源里有對(duì)應(yīng)的索引才顯示,不然不顯示,代碼如下:

        let data=_.cloneDeep(this.state.dataArray);
        this.props.sectionListData.map((item,index)=>{
            for (let i=0;i<data.length;i++){
                if (i==data.length-1){
                    data[i].data.push(item)
                    break
                }else if (data[i].key==makePy(item.name.toUpperCase())){
                    data[i].data.push(item)
                    break
                }else {
                    continue
                }
            }
        })
        let delData = []
        let letterData = []
        for (var i in data){
            if (data[i].data.length!=0){
                delData.push(data[i])
                letterData.push(data[i].key)
            }
        }

sectionListData是數(shù)據(jù)源數(shù)組,makePy即為獲取每個(gè)字符串的首字母方法,最后得到的letterData數(shù)據(jù)即為索引數(shù)組,然后絕對(duì)定位渲染出索引:

<View style={[styles.letterView,this.props.letterViewStyle]}>
        {
            letterData.map((item,index)=>{
                 let otherStyle=[]
                 if (index==letterData.length-1){
                    if (item==this.props.otherAlphabet){
                         otherStyle.push({width: 20})
                    }
                 }
              return(
                    <TouchableWithoutFeedback key={'letter_'+index} onPress=    
                      {()=>{
                         this.sectionList.scrollToLocation({animated: this.props.scrollAnimation, itemIndex: 0,sectionIndex: index,viewOffset: (this.props.sectionHeight * (index + 1)) + (this.props.sectionHeaderHeight * index)})
                       }}>
                      <View style={[styles.letterItemView,otherStyle]}>
                          <Text numberOfLines={0} style={[styles.letterText,this.props.letterTextStyle]}>{item}</Text>
                       </View>
                    </TouchableWithoutFeedback>
               )
            })
        }
</View>

當(dāng)點(diǎn)擊每個(gè)索引的時(shí)候,就會(huì)觸發(fā)sectionList的scrollToLocation方法,最新版本已經(jīng)修復(fù)了點(diǎn)擊索引不準(zhǔn)確的問題。
遇到點(diǎn)擊索引不準(zhǔn)確問題,可以試著設(shè)置sectionHeight和sectionHeaderHeight
最后中間踩到的坑,做一些經(jīng)驗(yàn)總結(jié):

可能會(huì)有大量數(shù)據(jù)的時(shí)候,會(huì)有卡頓情況,所以推薦子組件繼承PureComponent,本開源組件默認(rèn)已經(jīng)做了這個(gè)功能,其次,會(huì)有遇到下滑加載緩慢,或者直接點(diǎn)擊后面的索引到最后的位置會(huì)出現(xiàn)白屏等待很久的問題,這種處理方法可以加個(gè)initialNumToRender屬性,值為數(shù)據(jù)源的個(gè)數(shù),也就是全部渲染出來initialNumToRender={this.state.dataArray.length}

庫地址react-native-sectionlist-contacts

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容