如何封装一个功能完善的table组件*(react-native)

新手上路,请多包涵

问题描述

在公司任务中,需要实现一个功能齐全的table表格
需要支持:表头可点击,可操作按钮,可点击排序,.....

问题出现的环境背景及自己尝试过哪些方法

自己也封装了一个,效果不理想,性能较差,希望有一个更好的~

原型如下
微信截图_20191217103324.png

相关代码

myCode
`import React, { Component } from 'react'
import {

Text,
View,
FlatList,
TouchableOpacity,

} from 'react-native';
import { COLOR_SECOND_COLOR } from "../../constant/ColorConstant";
import { renderEmptyComponent } from "../../page/util/PageUtil";

export default class TabView extends Component {

static defaultProps = {
    tabHeadBg: '#2b7888',//列表背景色
    tabHeadHeight: 36, //列表头部高度
    tabHeadSeparatorLineColor: '#FFFFFF',//列表头部分割线颜色
    SeparatorLineColor: '#EAEAEA',//列表分割线颜色
    tabHeadTextColor: '#FFFFFF',//列表头部文字颜色
    tabHeadTextFontSize: 20,//列表头部文字大小
    tabMarginTop: 10,
    redPointIndexArray: [],
    borderLeftWidth: 1,
    borderLeftWidthIdx0: -1,
    borderRightWidth: 1,
    rowHeight: 40,
    onPressColumn: (i)=> {}
}

constructor(props) {
    super(props)
    this.state = {
        data: this.props.data,
        isAllCheck: this.props.isAllCheck,
        onPressColumnList: this.props.onPressColumnList
    }
    this.tabHeads = this.props.tabHeads
    this.tabRowWidth = this.props.tabRowWidth
}

componentWillReceiveProps(nextProps) {
    this.setState({ data: nextProps.data, isAllCheck: nextProps.isAllCheck, onPressColumnList: nextProps.onPressColumnList })
}

render() {
    const { flatListProps } = this.props;
    const selfFlatListProps = {};
    if (!flatListProps || !flatListProps.hasOwnProperty('ListFooterComponent')) {
        selfFlatListProps['ListFooterComponent'] = this._renderListFooterComponent;
    }

    return (
        <View style={{ flex: 1 }}>

            {this.props.isOnPressColumn ?
                <View style={[{
                    backgroundColor: this.props.tabHeadBg,
                    flexDirection: 'row',
                    height: this.props.tabHeadHeight,
                    width: this.deviceWidth
                }, this.props.tabHeadStyle]}>

                    {this.tabHeads.map((item, i) => {

                        if (item.title === '···') {
                            return (this.allCheckView(i))
                        } else {
                            return (this.onPressHeadView(item, i))
                        }
                    })}
                </View>
                :
                <View style={[{
                    backgroundColor: this.props.tabHeadBg,
                    flexDirection: 'row',
                    height: this.props.tabHeadHeight,
                    width: this.deviceWidth
                }, this.props.tabHeadStyle]}>
                    {this.tabHeads.map((item, i) => {
                        if (item === '···') {
                            return (this.allCheckView(i))
                        } else {
                            return (this.columnHeadView(item, i))
                        }

                    })}
                </View>
            }

            <FlatList
                ref={(ref) => this.flatList = ref}
                style={{ flex: 1, marginTop: this.props.tabMarginTop }}
                data={this.state.data}
                keyExtractor={(item, index) => `${item.toString()}_${index}`}
                renderItem={this.props.renderItem}
                // getItemLayout={(data, index) => (
                //     {length: 41, offset: 41 * index, index}
                //   )}
                ListEmptyComponent={() => renderEmptyComponent()}
                ItemSeparatorComponent={() =>
                    //分割线
                    <View
                        style={{ height: 1, backgroundColor: this.props.SeparatorLineColor }}>
                    </View>

                }
                {...selfFlatListProps}
                {...flatListProps}
            />
        </View>
    )
}

_renderListFooterComponent = () => {
    return <View style={{ height: 1, backgroundColor: this.props.SeparatorLineColor }} />;
}

_getFlatList = () => {
    return this.flatList;
}


/**
 * 可点击的头部view
 * @param {*} item
 * @param {*} i
 */
onPressHeadView(item, i) {
    let isOnPressColumn = false;
    let isSort = false;
    let currentCheck = false;
    this.state.onPressColumnList.map((opci, index) => {
        if (opci.id === i) {
            currentCheck = opci.currentCheck;
            isOnPressColumn = true;
            isSort = opci.isSort;
        }
    });
    return (
        <TouchableOpacity key={i} style={{
            flex: this.tabRowWidth ? this.tabRowWidth[i] : 1,
            justifyContent: 'center',
            flexDirection: 'row',
            alignItems: 'center',
            borderColor: this.props.tabHeadSeparatorLineColor,
            borderLeftWidth: i === this.props.borderLeftWidthIdx0 ? 0 : this.props.borderLeftWidth,
            borderTopWidth: 1,
            borderRightWidth: i === this.tabHeads.length - 1 ? this.props.borderRightWidth : 0,
            borderBottomWidth: 0,
        }} onPress={() => {
            if (isOnPressColumn) {
                this.props.onPressColumn(i);
            }
        }}>
            {this.props.redPointIndexArray.indexOf(i) !== -1 ?
                <View style={{
                    width: 5,
                    height: 5,
                    borderRadius: 2.5,
                    backgroundColor: '#ff0000',
                    // marginRight: 10
                }} />
                : null
            }

            {isOnPressColumn ?
                <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', }}>
                    <Text style={{color: this.props.tabHeadTextColor, fontSize: this.props.tabHeadTextFontSize}}>{item}</Text>
                    <View style={{ justifyContent: 'center' ,marginLeft: 2}}>
                        <Text style={{ fontSize:5, color: currentCheck &&  isSort ? '#ff0000' : '#ffffff' }}>▲</Text>
                        <Text style={{ fontSize:5, color: currentCheck && !isSort ? '#ff0000' : '#ffffff' }}>▼</Text>
                    </View>
                </View>
                :
                <Text style={{
                    color: this.props.tabHeadTextColor,
                    fontSize: this.props.tabHeadTextFontSize
                }}>{item}
                </Text>
            }

        </TouchableOpacity>
    )
}


/**
 * 默认头部view
 * @param {*} item
 * @param {*} i
 */
columnHeadView(item, i) {
    return (
        <View key={i} style={{
            flex: this.tabRowWidth ? this.tabRowWidth[i] : 1,
            justifyContent: 'center',
            flexDirection: 'row',
            alignItems: 'center',
            borderColor: this.props.tabHeadSeparatorLineColor,
            borderLeftWidth: i === this.props.borderLeftWidthIdx0 ? 0 : this.props.borderLeftWidth,
            borderTopWidth: 1,
            borderRightWidth: i === this.tabHeads.length - 1 ? this.props.borderRightWidth : 0,
            borderBottomWidth: 0,
        }}>
            {this.props.redPointIndexArray.indexOf(i) !== -1 ?
                <View style={{
                    width: 5,
                    height: 5,
                    borderRadius: 2.5,
                    backgroundColor: '#ff0000',
                    // marginRight: 10
                }} />
                : null
            }
            <Text style={{
                color: this.props.tabHeadTextColor,
                fontSize: this.props.tabHeadTextFontSize
            }}>{item}</Text>
        </View>
    )
}


/**
 * 全选view
 */
allCheckView(i) {
    return (
        <TouchableOpacity key={i} style={{
            flex: this.tabRowWidth ? this.tabRowWidth[i] : 1,
            justifyContent: 'center',
            flexDirection: 'row',
            alignItems: 'center',
            borderColor: this.props.tabHeadSeparatorLineColor,
            borderLeftWidth: i === this.props.borderLeftWidthIdx0 ? 0 : this.props.borderLeftWidth,
            borderTopWidth: 1,
            borderRightWidth: i === this.tabHeads.length - 1 ? this.props.borderRightWidth : 0,
            borderBottomWidth: 0,
        }} onPress={() => this.props.onAllCheck()}>
            {this.state.isAllCheck ?
                <View style={{
                    width: 8,
                    height: 8,
                    backgroundColor: "#f4d000"
                }}>
                </View>
                :
                <View style={{
                    width: 8,
                    height: 8,
                    backgroundColor: "#ffffff"
                }}>
                </View>
            }
        </TouchableOpacity>
    )
}

}
`

你期待的结果是什么?实际看到的错误信息又是什么?

望大神指点一番~

阅读 1.9k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题