RN研發(fā)記(二):FlatList局部更新子節(jié)點(diǎn)

上一篇文章記錄了在RN中如何響應(yīng)Hover事件,現(xiàn)在,我想仿照RN中<TouchableHighlight>標(biāo)簽實(shí)現(xiàn)<HoverBoard>,目的是為了不在具體UI代碼中進(jìn)行業(yè)務(wù)邏輯代碼的頻繁copy,最終的效果基本如下:

<FlatList
  data={[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]}
  keyExtractor={() => ++i}
  numColumns={6}
  style={{paddingHorizontal: 15,}}
  renderItem={({item}) => (
    <HoverBoard
      onHoverChanged={this._onHoverChanged}
    >
      <Image source={require('./img/icon.jpg')} style={{width: 150, height: 150}}/>
      <Title ref="text"/>
    </HoverBoard>
  )}
/>

<HoverBoard>在加載之后會(huì)計(jì)算每個(gè)子節(jié)點(diǎn)的實(shí)際位置,然后監(jiān)聽Hover事件,在發(fā)現(xiàn)自身狀態(tài)發(fā)生變化時(shí),會(huì)回調(diào)“this._onHoverChanged”方法來更新界面。

簡單說一下實(shí)現(xiàn)背景,在Android中有很多的監(jiān)聽器,可以很簡單的實(shí)現(xiàn)類似FlatList組件中子節(jié)點(diǎn)狀態(tài)的回調(diào),但是看了一段時(shí)間的RN或者說JavaScript,發(fā)現(xiàn)這件事情做起來好像有些麻煩(好吧,我承認(rèn)目前對(duì)JS還不太在行。。)。
我為什么一定要這樣做呢,簡略的說一下探索的過程,最初我采用類似下面的方式實(shí)現(xiàn)FlatList的子節(jié)點(diǎn):

<View>
  <Image source={require('../img/icon.jpg')} style={{width: len, height: len}}/>
  <Text ref="text" style={styles.text}>
    ({this.state.left}, {this.state.right}), ({this.state.top}, {this.state.bottom})
  </Text>
</View>

后來發(fā)現(xiàn),在現(xiàn)有的設(shè)備上,子節(jié)點(diǎn)每次整體刷新需要接近20ms的時(shí)間,這真的是無法忍受。因?yàn)楫吘怪皇菍?shí)現(xiàn)Demo,所以我嘗試單獨(dú)刷新<Text>標(biāo)簽,在經(jīng)過了一番折騰之后,發(fā)現(xiàn)這樣做確實(shí)讓效率提高了十倍以上。
從以往的開發(fā)經(jīng)驗(yàn)中可以得到一點(diǎn):子節(jié)點(diǎn)的布局肯定不會(huì)如上面那樣簡單,換句話說,它肯定是一個(gè)"Component"。
我肯定不愿意讓多余的業(yè)務(wù)邏輯插入到這個(gè)"View"中,閱讀了一下<TouchableHighlight>的源碼,發(fā)現(xiàn)渲染部分的代碼是醬嬸的:

render: function() {
  return (
    <View
      ... ...>
      {React.cloneElement(
        React.Children.only(this.props.children),
        {
          ref: CHILD_REF,
        }
      )}
      {... ...}
    </View>
  );
}

經(jīng)過了一番折騰,發(fā)現(xiàn)這段代碼的意思應(yīng)該是將源代碼中的該組件的子節(jié)點(diǎn)克隆并轉(zhuǎn)換成界面上UI元素,“React.Children.only”方法目前還不是非常理解,大致理解為修改單獨(dú)元素的屬性。

在折騰代碼的時(shí)候,發(fā)現(xiàn)自己對(duì)于“this.refs”和“this.props.children”的區(qū)別鬧不明白了,現(xiàn)在的理解是“this.refs”代表的應(yīng)該是界面顯示之后的節(jié)點(diǎn)對(duì)象,而“this.props.children”應(yīng)該是指源代碼中書寫的該標(biāo)簽的子節(jié)點(diǎn)集,好吧,我知道這么說也還是有點(diǎn)繞。
最終通過下面的代碼回調(diào)到外部:

_hoverListener = (msg) => {
  let {x: hx, y: hy} = msg;
  let inHover = hx >= this.left && hx <= this.right && hy >= this.top && hy <= this.bottom;

  const isChanged = this._inHover != inHover;

  if (isChanged) {
    this.props.onHoverChanged && this.props.onHoverChanged(this.refs.text, inHover);
    this._inHover = inHover;
  }
}
最后編輯于
?著作權(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)容