如何在FlatList中有效地呈现不同的视图

时间:2018-06-30 14:32:53

标签: javascript react-native react-native-flatlist

我正在创建一个日历组件,其中包含2个带有FlatList的视图。每个视图都与一个不同的数据源关联。具体来说,“视图1”将显示一个月中的所有日子,而“视图2”将显示一周中的所有日子。

Link to video demo, button of year is for view switching

为简单起见,每个月/周视图由日期表示为更大数组中的数组项。

例如,month数组中的每个项目都是一个月内的唯一数据。大小为12的数组每个月都有12个唯一的日期。然后,每个Date()对象都会向下传递给我的子组件,以进行正确的渲染。此特定month数组的结果是一个完整的12个月日历列表。

注意:为了提高性能,我的子组件将仅呈现current month -1current monthcurrent month +1,其他所有月份将在用户滚动离开时有条件地呈现。 / p>

[
    ...
    Wed May 30 2018 21:51:47 GMT+0800 (+08),
    Sat Jun 30 2018 21:51:47 GMT+0800 (+08),
    Mon Jul 30 2018 21:51:47 GMT+0800 (+08),
    ...
]

视图2(周视图)也是如此。除了现在我的数据包含一个月中所有星期的一周中唯一的几天。

在实施这种方法之前,我尝试从子组件中破解一些东西。例如,当用户单击按钮切换视图时,它将沿道具向下传递,并带有当前的Date()对象,以通知子项有条件地渲染其他视图。这基本上是在ViewFlatList之间切换。嵌套FlatList是一个坏主意,因为两个列表都朝着同一方向滚动。

更不用说我的日历组件涉及到选定的月份。我实现的另一种解决方案是通过从month中窃取索引,仅对两个视图使用keyExtractor数组。例如,一旦用户jumps从一个月到另一个月,我就会立即为列表重新建立索引,但是不久我意识到这是一种反模式,只会导致更多问题。

  

注意:我已经在所有孩子中实施了shouldComponentUpdate   组件。因此,仅滚动1个View应该没有问题,大小   数据源完全不会受影响,因为只有更改   -10+1月份的发生情况将得到反映。的   我的组件的瓶颈仅在切换视图时才会发生。

简而言之,现在我求助于当前的解决方案,其中在array中有2个不同视图的2个不同数据源(FlatList)。我有一个按钮供用户在模式之间切换。问题在于,每次通过从onViewableItemsChanged调用此道具FlatList重新实例化视图时,都要花费一些时间来切换模式(设置状态),这涉及一些复杂的计算。有更好的方法吗?

代码(父母)

renderCalendarList = () => {
        return (
            <FlatList
                pageSize={1}
                horizontal={true}
                pagingEnabled={true}
                scrollEnabled={true}
                keyExtractor={this.keyExtractor}
                ref={(c) => this.calendarList = c}
                getItemLayout={this.getItemLayout}
                renderItem={this.renderCalendarComponent}
                onViewableItemsChanged={this.onViewableItemsChanged}
                data={(this.state.weekMode ? this.state.weekRows : this.state.rows)} />
        )
    }

switchView = () => {
        this.setState({ weekMode: !this.state.weekMode });

        // next week is going to be month view
        if (this.state.weekMode) {
            const mYClone = this.state.monthYears.slice(0);
            const selectedDay = DateUtils.formatDateInMY(this.props.selectedDay);

            for (let i = 0; i < mYClone.length; i++) {
                if (selectedDay === mYClone[i]) {
                    this.setState({ currentMonth: this.props.selectedDay })
                    this.calendarList.scrollToIndex({ animated: false, index: i });
                }
            }
        } else {             // next week is going to be week view
            const rowClone = this.state.weekRows.slice(0);

            for (let i = 0; i < rowClone.length; i++) {
                if (isSameWeek(rowClone[i], this.props.selectedDay)) {
                    this.setState({ currentMonth: rowClone[i] });
                    this.calendarList.scrollToIndex({ animated: false, index: i });
                }
            }
        }
    }

代码(儿童)

render() {
        const { container, monthContainer, weekContainer } = styles;
        const { currentMonth, firstDay, style, weekMode } = this.props;
        if (!weekMode) {
            const days = DateUtils.populateMonth(currentMonth, firstDay);
            const weeks = [];
            while (days.length) {
                weeks.push(this.renderWeek(days.splice(0, 7), weeks.length));
            }
            return (
                <View style={[container, style]}>
                    <View style={[monthContainer]}>{weeks}</View>
                </View>
            )
        } else {
            const startDay = subDays(currentMonth, 3); // focus on middle
            const endDay = addDays(startDay, 6)
            const days = eachDay(startDay, endDay, 1);
            const daysToRender = [];
            days.forEach((day, dayID) => {
                daysToRender.push(this.renderDay(day, dayID))
            });
            return (
                <View style={style}>
                    <View style={[weekContainer]}>
                        {daysToRender}
                    </View>
                </View>
            )
        }
    }

Link to video demo, button of year is for view switching

0 个答案:

没有答案