美文网首页
ReactNative中的高阶组件(HOC)和继承详解

ReactNative中的高阶组件(HOC)和继承详解

作者: iOS小童 | 来源:发表于2021-01-25 16:36 被阅读0次

    ReactNative中的高阶组件(HOC)和继承详解

    共同点:

    1. 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
    2. 继承也是用于解决复用代码的一种技巧

    不同点:

    1. 高阶组件是参数为组件,返回值为新组件的函数
    2. 继承是类继承类,是面向对象的一大特点

    本文以FlatList为例,详解高阶组件和继承的使用!为啥是FlatList尼?
    因为FlatList使用广泛,造成大量重复代码,仅仅是因为样式不同而导致,使用高阶组件,可以传入被包裹的样式组件,由高阶组件统一实现FlatList的方法,由此可以减少重复代码,减少耦合,其他场景等同

    高阶组件(HOC)

    高阶组件的样式:

    function HOC(WrappedComponent) {
        return class Component extends React.Component {
        render() {
          // 将WrappedComponent组件包装在容器中,而不对其进行修改。Good!
          return <WrappedComponent {...this.props} />;
        }
      }
    
    

    而我们要改变的不是传入的FlatList,而是renderItem组件,首先在高阶组件中实现FlatList:

     keyExtractor = (item, index) => {
                return index.toString()
            }
    
            listHeaderComponent = () => {
                return (
                    <View style={{marginTop: Dimens.dx_60}}/>
                )
            }
    
            listFooterComponent = () => {
                if (this.state.showFoot) {
                    return (
                        <View style={styles.footView}>
                            <Text style={styles.footText}>
                                没有更多数据了
                            </Text>
                        </View>
                    )
                } else {
                    return (
                        <View style={styles.footLoadingView}>
                            <Text style={styles.footLoadingText}>
                                正在加载中...
                            </Text>
                        </View>
                    )
                }
            }
            onEndReached = () => {
                if (this.hasNextPage === 1) {
                    this.pageIndex++,
                        this.setState({
                            showFoot: false
                        })
                    this.getNetworkingDataFunction(this.pageIndex, 20)
                } else {
                    this.setState({
                        showFoot: true
                    })
                }
            }
    
            flatListRenderItem = (item) => {
                return (
                    <WrappedComponent {...this.props} {...item} />
                )
            }
    
            onRetry = () => {
                this.getNetworkingDataFunction(this.pageIndex, 20)
            }
    
            render() {
                if (this.state.error) {
                    return (
                        <LoadFailView onRetry={this.onRetry}/>
                    )
                }
                if (this.state.list && this.state.list.length) {
                    return (
                        <View style={{backgroundColor: Colors.bgColor, flex: 1}}>
                            <FlatList
                                keyExtractor={this.keyExtractor.bind(this)}
                                horizontal={false}
                                data={this.state.list}
                                numColumns={WrappedComponent.numOfColumn()}
                                showsVerticalScrollIndicator={false}
                                renderItem={this.flatListRenderItem.bind(this)}
                                ListHeaderComponent={this.listHeaderComponent.bind(this)}
                                ListFooterComponent={this.listFooterComponent.bind(this)}
                                onEndReached={this.onEndReached.bind(this)}
                                onEndReachedThreshold={0.01}
                            />
                        </View>
                    )
                } else {
                    return <EmptyView text={this.state.empty}/>
                }
    
            }
        }
    

    毫无疑问在以上代码中你已经看到flatListRenderItem返回的组件才是被包裹组件,现在只需要解决数据问题,高阶组件FlatList就完成了

    由于高阶组件中获取不了被包裹组件的实例,需要在被包裹组件中声明静态网络请求方法:getNetworkingFunction
    
    /**
       * Takes network data from server
       * 无默认配置,组件中有网络请求需实现异步Promise:
       **/
    getNetworkingDataFunction = (pageIndex, pageSize) => {
       WrappedComponent.getNetworkingFunction(pageIndex, pageSize).then(results => {
    
                }).catch(error => {
                    
                                })
    }
    

    在被包裹组件中:

    此处需要用到异步Promise
    
    static getNetworkingFunction = (pageIndex,pageSize)=> {
           return new Promise(function (resolve, reject) {
               requestGetIntegralExchangeRecordList(pageIndex, pageSize).then(results => {
                   resolve(results)
               }).catch(error => {
                   reject(error)
               })
           })
        }
    
    用来控制FlatList的column
    
    static numOfColumn = () =>{
          return 1;
        }
        
    传入各样式的item组件即可
        
    render() {
    
    }
    

    继承

    父类:
    
    export default class BaseComponent extends React.Component {
    
    }
    
    子类:
    export default class childComponent extends BaseComponent {
    
    }
    
    

    父类中实现FlatList

    /**
         * Takes network data from server
         * 无默认配置,必须继承实现
         **/
        getNetworkingDataFunction = () =>{
    
        }
    
        /**
         * Takes an item from data and renders it into the list. Typical usage:
         * 无默认配置,必须继承实现
         */
        flatListRenderItem = (item) =>{
    
        }
    
        /**
         * Rendered at the very beginning of the list.
         * 默认配置如下,可通过继承实现修改
         */
        listHeaderComponent = () => {
            return (
                <View style={{marginTop: Dimens.dx_60}}/>
            )
        }
        /**
         * Rendered at the very end of the list.
         * 默认配置如下,可通过继承实现修改
         */
        listFooterComponent = () => {
            if (this.state.showFoot) {
                return (
                    <View style={styles.footView}>
                        <Text style={styles.footText}>
                            没有更多数据了
                        </Text>
                    </View>
                )
            } else {
                return (
                    <View style={styles.footLoadingView}>
                        <Text style={styles.footLoadingText}>
                            正在加载中...
                        </Text>
                    </View>
                )
            }
        }
    
        keyExtractor = (item, index) => {
            return index.toString()
        }
    
        onEndReached = () =>{
            if (this.hasNextPage === 1) {
                this.pageIndex++,
                    this.setState({
                        showFoot: false
                    })
                this.getNetworkingDataFunction(this.pageIndex,20)
            } else {
                this.setState({
                    showFoot: true
                })
            }
        }
    
        render(){
            if (this.state.list && this.state.list.length){
                return (
                    <View style={{backgroundColor: Colors.bgColor, flex: 1}}>
                        <FlatList
                            keyExtractor={this.keyExtractor.bind(this)}
                            horizontal={false}
                            data={this.state.list}
                            showsVerticalScrollIndicator={false}
                            renderItem={this.flatListRenderItem.bind(this)}
                            ListHeaderComponent={this.listHeaderComponent.bind(this)}
                            ListFooterComponent={this.listFooterComponent.bind(this)}
                            onEndReached={this.onEndReached.bind(this)}
                            onEndReachedThreshold={0.01}
                        />
                    </View>
                )
            }else {
                return <EmptyView text={this.state.emptyText}/>
            }
    
        }
    

    在子类中去重写父类的方法

    
    * 网络请求方法:getNetworkingDataFunction
    * render内容展示:flatListRenderItem
    
    getNetworkingDataFunction = (pageIndex,pageSize) => {
    
            requestGetIntegralExchangeRecordList(pageIndex, pageSize).then(results => {
            
            }).catch(error => {
    
            })
        }
    
    flatListRenderItem = ({item}) =>{
            return (
                <TouchableOpacity onPress={event => {
                    this.onClick(item)
                }}>
                    <RenderItem item={item} />
                </TouchableOpacity>
            )
        }
    
    onClick(item) {
     }
     
    class RenderItem extends React.Component{
    
    }
    

    那为什么react-native不推荐使用继承?
    react中推荐使用组合和高阶组件来替代继承,网上关于react的继承也是微乎其微,对于iOS出身的我来说,继承主要有一下缺点:

    1. 父类的内部细节对子类是可见的
    2. 如果父类做了修改,所有涉及的子类必须修改,高耦合。
    3. 继承也有可能使程序变得难以阅读。调用一个方法时,有时很难判断它是在哪定义的,子类中查找问题必须去父类中查看

    相关文章

      网友评论

          本文标题:ReactNative中的高阶组件(HOC)和继承详解

          本文链接:https://www.haomeiwen.com/subject/nklizktx.html