irpas技术客

React-Native中的FlatList学习记录(一)之keyExtractor_隔壁老何_keyextractor

未知 1858

写作时间:20年末或21年初吧具体时间记不得了 React-Native版本:0.63.2 目标平台:Android、iOS

FlatList是RN中的一个重要组件,打算做一个系列,对其使用方法和注意事项进行系统的学习整理,这期主要是记录keyExtractor的若干使用场景和对应现象

情景1:

父组件维护一组复杂的列表数据,其中keyExtractor取列表中每一项的key值,当点击按钮之后,数据更新。

代码如下:

//App.js import React from 'react'; import {View, Button, FlatList} from 'react-native'; import Item from './Item'; export default class App extends React.Component { constructor() { super(); this.state = { list: [ {key: '1', data: {name: 'aaa', age: 11}}, {key: '2', data: {name: 'bbb', age: 22}}, {key: '3', data: {name: 'ccc', age: 33}}, {key: '4', data: {name: 'ddd', age: 44}}, {key: '5', data: {name: 'eee', age: 55}}, ], }; this.temp = [ {key: '6', data: {name: 'fff', age: 66}}, {key: '7', data: {name: 'ggg', age: 77}}, {key: '8', data: {name: 'hhh', age: 88}}, ]; } render() { console.log('App_render()'); return ( <View> {this.renderButton()} {this.renderList()} </View> ); } renderButton = () => { console.log('App_renderButton()'); return <Button title={'RefreshData'} onPress={this.onButtonPress} />; }; renderList = () => { console.log('App_renderList()'); return ( <FlatList data={this.state.list} renderItem={this.renderItem} keyExtractor={this.keyExtractor} /> ); }; renderItem = ({item}) => { return <Item itemData={item} />; }; onButtonPress = () => { this.setState({list: this.temp}); }; keyExtractor = (item) => { return item.key; }; } //Item.js import React from 'react'; import {Text} from 'react-native'; export default class Item extends React.Component { constructor(props) { super(props); console.log('Item_constructor()', 'key:', this.props.itemData.key); } render() { console.log('Item_render()', 'key:', this.props.itemData.key); return <Text>{this.props.itemData.data.name}</Text>; } }

控制台日志如下:

LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_constructor() key: 1 LOG Item_render() key: 1 LOG Item_constructor() key: 2 LOG Item_render() key: 2 LOG Item_constructor() key: 3 LOG Item_render() key: 3 LOG Item_constructor() key: 4 LOG Item_render() key: 4 LOG Item_constructor() key: 5 LOG Item_render() key: 5 ->点击按钮触发数据更新,界面重新渲染 LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_constructor() key: 6 LOG Item_render() key: 6 LOG Item_constructor() key: 7 LOG Item_render() key: 7 LOG Item_constructor() key: 8 LOG Item_render() key: 8

小结:若数据变化且列表中的key值与原数据不同,则子组件会触发构造函数,也就是说,会产生新的子组件

情景2:

与情景1类似,但keyExtractor设置为列表数据中的name,再观察结果

代码的修改如下:

//App.js keyExtractor = (item) => { return item.data.name; };

控制台日志如下:

LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_constructor() key: 1 LOG Item_render() key: 1 LOG Item_constructor() key: 2 LOG Item_render() key: 2 LOG Item_constructor() key: 3 LOG Item_render() key: 3 LOG Item_constructor() key: 4 LOG Item_render() key: 4 LOG Item_constructor() key: 5 LOG Item_render() key: 5 ->点击按钮触发数据更新,界面重新渲染 LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_constructor() key: 6 LOG Item_render() key: 6 LOG Item_constructor() key: 7 LOG Item_render() key: 7 LOG Item_constructor() key: 8 LOG Item_render() key: 8

小结:可以看出keyExtractor无论是设置成数据中的key还是data.name,只要是新的数据中keyExtractor所对应的数据发生了改变,就必然会触发构造函数,创建新的子组件。或者说子组件的创建与keyExtractor绑定的数据层级无关。

情景3:

当数据更新时,如果新的数据的keyExtractor所对应的值无新内容,子组件的情况?

以情景1作为基础,keyExtractor对应列表数据中的key值,修改用于更新的数据this.temp,修改内容如下:

//App.js this.temp = [ {key: '1', data: {name: 'fff', age: 66}}, {key: '2', data: {name: 'ggg', age: 77}}, {key: '3', data: {name: 'hhh', age: 88}}, ];

可以看出,key值没有新的内容,但是内部data数据已经完全修改,最终控制台的日志如下:

LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_constructor() key: 1 LOG Item_render() key: 1 LOG Item_constructor() key: 2 LOG Item_render() key: 2 LOG Item_constructor() key: 3 LOG Item_render() key: 3 LOG Item_constructor() key: 4 LOG Item_render() key: 4 LOG Item_constructor() key: 5 LOG Item_render() key: 5 ->点击按钮触发数据更新,界面重新渲染 LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_render() key: 1 LOG Item_render() key: 2 LOG Item_render() key: 3

通过上面的日志可以看出,不再有新的子组件生成

情景4:

基于情景3,如果新数据中有部分数据含有新的key值

需要替换的代码如下:

//App.js this.temp = [ {key: '1', data: {name: 'fff', age: 66}}, {key: '6', data: {name: 'ggg', age: 77}}, {key: '7', data: {name: 'hhh', age: 88}}, ];

日志如下:

LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_constructor() key: 1 LOG Item_render() key: 1 LOG Item_constructor() key: 2 LOG Item_render() key: 2 LOG Item_constructor() key: 3 LOG Item_render() key: 3 LOG Item_constructor() key: 4 LOG Item_render() key: 4 LOG Item_constructor() key: 5 LOG Item_render() key: 5 ->点击按钮触发数据更新,界面重新渲染 LOG App_render() LOG App_renderList() LOG App_renderButton() LOG Item_render() key: 1 LOG Item_constructor() key: 6 LOG Item_render() key: 6 LOG Item_constructor() key: 7 LOG Item_render() key: 7

由日志可以看出,keyExtractor决定了子组件是否需要新建。只要有新的keyExtractor,那么就会构造新的子组件


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #keyextractor #代码如下Appjsimport #React #from #reactimport #v