ReactNative进阶(四十七):自定义组件_react native组件开发,【严选】

109 阅读3分钟

optionalElement: PropTypes.element,

//可以定义类型为某个类的实例,这里使用JS的instanceOf操作符实现 optionalMessage: PropTypes.instanceOf(Message),

//指定枚举类型:你可以把属性限制在某些特定值之内 optionalEnum: PropTypes.oneOf(['News', 'Photos']),

// 指定多个类型:也可以把属性类型限制在某些指定的类型范围内 optionalUnion: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.instanceOf(Message) ]),

// 指定某个类型的数组 optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

// 指定类型为对象,且对象属性值是特定的类型 optionalObjectOf: PropTypes.objectOf(PropTypes.number),

//指定类型为对象,且可以规定哪些属性必须有,哪些属性可以没有 optionalObjectWithShape: PropTypes.shape({ optionalProperty: PropTypes.string, requiredProperty: PropTypes.number.isRequired }),

// 指定类型为对象,且可以指定对象的哪些属性必须有,哪些属性可以没有。如果出现没有定义的属性,会出现警告。 //下面的代码optionalObjectWithStrictShape的属性值为对象,但是对象的属性最多有两个,optionalProperty 和 requiredProperty。 //出现第三个属性,控制台出现警告。 optionalObjectWithStrictShape: PropTypes.exact({ optionalProperty: PropTypes.string, requiredProperty: PropTypes.number.isRequired }),

//加上isReqired限制,可以指定某个属性必须提供,如果没有出现警告。 requiredFunc: PropTypes.func.isRequired, requiredAny: PropTypes.any.isRequired,

// 也可以指定一个自定义的验证器。如果验证不通过,它应该返回Error对象,而不是console.warn 或抛出错误。oneOfType中不起作用。 customProp: function(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error( 'Invalid prop ' + propName + ' supplied to' + ' ' + componentName + '. Validation failed.' ); } },

//也可以提供一个自定义的验证器 arrayOf和objectOf。如果验证失败,它应该返回一个Error对象。 //验证器用来验证数组或对象的每个值。验证器的前两个参数是数组或对象本身,还有对应的key。 customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { if (!/matchme/.test(propValue[key])) { return new Error( 'Invalid prop ' + propFullName + ' supplied to' + ' ' + componentName + '. Validation failed.' ); } })


使用时,父组件通过属性名作为子组件参数形式传递,子组件通过`props`属性接收参数值,并可以通过设置默认值。



// ES6 class Greeting extends React.Component { static defaultProps = { name: 'stranger' } render() { return (

Hello, {this.props.name}
) } }


### 三、示例



#### 3.2 LinearLayout 组件



import React, { PureComponent } from 'react'; import { View, StyleSheet } from 'react-native'; import PropTypes from 'prop-types';

export default class LinearLayout extends PureComponent { static propTypes = { orientation: PropTypes.string, gravity: PropTypes.string, } static defaultProps = { orientation: 'vertical', gravity: undefined, } render() { return( <View style={{ flexDirection: (this.props.orientation === 'horizontal') ? 'row' : 'column' }}> {this.props.children} ) } }


**组件引用**

import LinearLayout from './LinearLayout'; ChildComponent


#### 3.2 列表展示


下面以封装`FlatList`展示列表信息,实现自定义组件。



/** ListView 使用说明 * extraData:数据变动会不会重新渲染列表 * * data:为数据源 * onLoading:上拉回调 * isLoading:上拉加载中 * hasMore:是否有更多数据 * hint:提醒用户文字 * isRefresh:下拉刷新中 * onRefresh:下拉刷新回调 * renderItem:item界面布局 */ import React from 'react'; import { StyleSheet, FlatList, View, Text, Image, ActivityIndicator, RefreshControl, Dimensions } from 'react-native'; import { Images } from '../../../constant/Images';

const { width, height } = Dimensions.get('window'); //获取手机的宽和高

export default (props) => ( <FlatList testID={props.testID} data={props.data} style={props.style || { flex: 1 }} refreshControl={ <RefreshControl onRefresh={props.isLoading ? null : props.onRefresh} refreshing={!props.isLoading && props.isRefresh} colors={props.colors || ['#108EE9', '#00FF00', '#FF0000']} /> } numColumns={props.numColumns || 1} extraData={props.extraData} renderItem={props.renderItem} keyExtractor={(_, index) => ${index}} indicatorStyle={props.indicatorStyle} ListEmptyComponent={EmptyView(props)} ListFooterComponent={FooterView(props)} ListHeaderComponent={props.ListHeaderComponent && props.ListHeaderComponent()} showsVerticalScrollIndicator={props.showIndicator} onEndReachedThreshold={props.threshold || 0.1} onScroll={props.onScroll} ItemSeparatorComponent={props.ItemSeparatorComponent} onEndReached={() => (props.isLoading || props.isRefresh || !props.hasMore ? null : props.onLoading())} /> );

// 数据为空是的视图 const EmptyView = (props) => props.isLoading || props.isRefresh ? null : ( <Image style={styles.icon} source={props.icon || showIcon(props.hint)} /> <Text style={styles.hint} onPress={hintLoad(props.hint) ? props.hintCallback || props.onLoading : null}> {props.hint || '没有查询到数据'} );

// 列表底部视图 const FooterView = (props) => props.isRefresh || (!props.isLoading && props.data.length == 0) ? null : ( {props.isLoading ? : null} <Text style={styles.loadText} onPress={hintLoad(props.hint) ? props.hintCallback : null}> {props.hint || (props.hasMore || props.isLoading ? '加载中...' : '没有更多数据!')} );

// 判断显示图片 function showIcon(msg) { if (msg == null || msg.indexOf('没有查询到数据') > 0 || msg.indexOf('数据为空') > 0) { return Images.nomes; } else if (msg.indexOf('超时') > 0) { return Images.nomes; } else if (msg.indexOf('异常') > 0) { return Images.nomes; } return Images.nomes; }

// 判断点击重新加载的条件 function hintLoad(msg) { return msg == null || msg.indexOf('异常') > 0 || msg.indexOf('失败') > 0 || msg.indexOf('超时') > 0; }

const styles = StyleSheet.create({ emptyLayout: { // marginTop: 96, marginTop: Math.floor(height / 4), alignItems: 'center', justifyContent: 'center', }, icon: { width: 128, height: 128, resizeMode: 'contain', }, hint: { color: '#666666', fontSize: 14, }, footerLayout: { minHeight: 38, alignItems: 'center', flexDirection: 'row', justifyContent: 'center', marginBottom: 20, }, indicator: { marginRight: 8, }, loadText: { color: '#999', fontSize: 14, }, });


**组件引用**

import { ListView } from './ListView.js'; <ListView data={bloc.getCity()} numColumns={2} hasMore={false} isLoading={true} onRefresh={_onRefreshEvent} // onLoading={_onLoadEvent} renderItem={sectionItems} isLoading={false} style={{marginTop: 10}} />


### 四、拓展阅读


**前端面试题汇总**

![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/4d053f02d8e54f4f87a378d61aec3f3e~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1771403970&x-signature=EOcoOvJbRBajKdEPClZZAeJoZos%3D)

**JavaScript**

![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/192e8363fae14fd5bca3eac7c53f34d7~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1771403970&x-signature=Rqg8qpmwDVIbDloJ1qDwQAlDEUI%3D)



**性能**

![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/d70d896548274516bed7a0b58572347a~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1771403970&x-signature=IQM%2BHtElz6L1vNtm5aCUdcBt7Go%3D)

**linux**

![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/07353806e19844f4a981cebc4080ed95~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1771403970&x-signature=4Aie74Cg54zKt4b9KU8H3QQJCuo%3D)

**前端资料汇总**

![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/ebd7c29fe6894ce4905853e0a6e5418b~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1771403970&x-signature=DJYnvwCZ%2Bo1g%2FhojkyyccLJPvns%3D)
**开源分享:https://docs.qq.com/doc/DSmRnRGxvUkxTREhO**