react-native开发常用组件封装
rn项目中各个技术版本:
最新版本:21年3月发布 0.64
工作中使用的是公司封装的rn,基于rn框架封装了路由 及redux的实现,并封装好用的创建页面的组件
(有些组件使用ant-mobile封装的组件,例如Checkbox, DatePicker, List, Picker等 https://antd-mobile-v2.surge.sh/index-cn, 就是ant design mobile 中RN的组件库,具体版本看项目中引入的版本 package.json中看然后选择对应的版本 https://3x.rn.mobile.ant.design/components/checkbox-cn/)
RN+antd-mobile+ramda
1、单选Radio的封装 (可以用组件库中的Radio)
重点看选中的样式:当点击时更新选中项的答案,触发重新渲染的逻辑,让选中项的样式为中间带实心圆
<KeyboardAwareScrollView>
{
questionOptionList.map((item, index) => {
const {
question, // 问题
optionList = [], // 选项数组
answer = 1, // 有的话就是该值,没有的话就是默认值1,初次登陆没有值
} = item;
const touchStyle = [styles.yesView, styles.yesColor];
const btnStyle = styles.yesBtn;
const centerStyle = styles.yesCenter;// 中间小点点
const textStyle = styles.yesText;
return (
// 问题渲染
<View style={styles.questionContainer} key={index}>
<View style={styles.questionView}>
<Text style={styles.questionText}>{`${index + 1}、${question}`}</Text>
{
item.description ? (
<TouchableOpacity
activeOpacity={0.5}
onPress={() => this.questionAlert(true, item.description)}
>
<Image source={PImageSet.editIntro} style={styles.change}/>
</TouchableOpacity>
)
: null
}
</View>
<View style={styles.answerView}>
{
// 问题答案渲染
optionList.map((x, idx) => (
<TouchableOpacity
style={touchStyle}
onPress={() => this.checkAnswer(index, x.key)}
activeOpacity={1}
>
<View style={btnStyle}>
{
answer === x.key ? (
<View style={centerStyle}/>
) : null
}
</View>
<Text style={textStyle}>{x.value}</Text>
</TouchableOpacity>
))
}
</View>
</View>
);
})
}
</KeyboardAwareScrollView>
yesView: {
justifyContent: 'flex-start',
alignItems: 'center',
flexDirection: 'row',
// width: 80,
height: 32,
borderRadius: 3,
paddingLeft: px(30),
paddingRight: px(30),
},
yesColor: {
backgroundColor: 'rgba(60, 90, 250, 0.1)',
},
yesBtn: { 外面小圆圈⭕️ ,不填背景色就是空圆
width: 16,
height: 16,
borderWidth: 1,
borderRadius: 10,
borderColor: '#4c83ff',
borderStyle: 'solid',
justifyContent: 'center',
alignItems: 'center',
},
yesCenter: { // 中间小点点
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: '#4c83ff',
},
yesText: {
marginLeft: 5,
color: '#4c83ff',
},
questionContainer: {
marginTop: px(25),
paddingLeft: 20,
},
questionView: {
width: ScreenWidth,
flexDirection: 'row',
},
questionText: {
color: '#333',
},
answerView: {
margin: px(10),
flexDirection: 'column',
},
noticeText: {
marginLeft: 20,
marginTop: px(20),
color: '#ff0000'
},
change: {
width: 17,
height: 17,
marginLeft: 5,
},
2、多选checkbox的封装(可选择1或多个, 使用ant mobile中RN)
// 多用于数组的遍历渲染选框,用时查官网
<CheckboxItem
checked={this.state.checkboxItem1}
onChange={event => {
this.setState({ checkboxItem1: event.target.checked });
}}
>
Option 1
</CheckboxItem>
<CheckboxItem>Option 2</CheckboxItem>
<CheckboxItem disabled>Option 3</CheckboxItem>
<CheckboxItem disabled checked>
Option 4
</CheckboxItem>
3、下拉选项的封装实现(类似select)
import React, { Component, PropTypes } from 'react';
import { Text, View, Picker, StyleSheet } from 'react-native';
import { px } from 'BizStyle';
const styles = StyleSheet.create({
container: {
display:'flex',
fontSize: px(26),
flexDirection: 'row',
},
select: {
height: px(40),
fontSize: px(26),
textAlign: 'center',
borderColor: '#FFF',
borderWidth: 1,
borderStyle: 'solid',
width: px(450),
},
label: {
height: px(40),
fontSize: px(26),
},
labelText:{
color:'#F00'
},
});
/**
* 基于Picker 创建的Select 组件
* 必传参数只有 下拉列表的数据 list
*/
export default class Select extends Component {
static propTypes = {
selected: PropTypes.string,
onChange: PropTypes.func,
list: PropTypes.array,
text: PropTypes.string,
};
static defaultProps = {
selected: '',
onChange: () => {},
list: [],
text: '',
};
constructor(props) {
super(props);
const { selected } = props;
this.state = {
selected,
};
}
onChange = (val) => {
const item = this.props.list.find(e => e.value === val);
this.setState({
selected: val,
});
this.props.onChange(item);
}
render() {
const { list = [], text } = this.props;
const { selected } = this.state;
return (
<View style={styles.container}>
{
text ?
<View style={styles.label}>
<Text style={styles.labelText}>{text}:</Text>
</View>
: null
}
<Picker
selectedValue={selected}
style={styles.select}
onValueChange={itemValue => this.onChange(itemValue)}
mode="dropdown"
prompt={'选择类型'}
>
{
list.map((item, index) =>
<Picker.Item label={item.label} value={item.value} key={index} />)
}
</Picker>
</View>
);
}
}
4、日期组件的封装实现(用RN原生组件,是在底部弹出的。或者使用ant mobile中的DatePicker组件)
// 使用
<List>
<DatePicker
value={this.state.value} // 绑定值
mode="datetime"
defaultDate={new Date()}
minDate={new Date(2015, 7, 6)}
maxDate={new Date(2026, 11, 3)}
onChange={this.onChange}
format="YYYY-MM-DD"
>
<List.Item arrow="horizontal">开始时间</List.Item> // 日期按钮前展示的内容
</DatePicker>
</List>
5、弹框提示的实现(ToolTip、Alert)
6、二次确认弹框的实现(简单提示文案,没有复杂的操作。有些需要考虑弹框有输入框等操作时情况)
// 使用react-native中的View Text封装
import React, { PropTypes } from 'react';
import {
View,
StyleSheet,
Text,
TouchableOpacity,
} from 'react-native';
const styles = StyleSheet.create({
contain: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
top: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
},
load: {
marginHorizontal: 32.5,
backgroundColor: '#FFFFFF',
borderRadius: 4,
},
title: {
height: 60,
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
titleText: {
color: '#1E2C32',
fontSize: 18,
fontWeight: '500',
},
loadAction: {
flexDirection: 'row',
alignItems: 'center',
height: 50,
borderColor: '#DDDDDD',
borderTopWidth: 1,
},
basicAction: {
height: 50,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
basicActionText: {
fontSize: 18,
color: '#7095F5',
},
line: {
position: 'absolute',
left: 0,
top: 0,
bottom: 0,
width: 0.5,
backgroundColor: '#DDDDDD',
},
content: {
marginHorizontal: 18,
marginBottom: 25,
},
contentText: {
color: '#888888',
fontSize: 15,
lineHeight: 20,
},
});
const Action = ({ style, text, action, line = false }) => (
<TouchableOpacity
onPress={action}
style={[styles.basicAction, style]}
>
{line ? <View style={styles.line}/> : null}
<Text style={[styles.basicActionText, text === '取消' ? { color: '#000000' } : {}]}>
{text}
</Text>
</TouchableOpacity>
);
Action.propTypes = {
style: PropTypes.object,
text: PropTypes.string,
action: PropTypes.func,
line: PropTypes.bool,
};
const EditAlert = ({
title,
style,
cancel,
cancelText,
sure,
sureText,
content,
contentStyle
}) => (
<View style={[styles.contain, style]}>
<View style={styles.load}>
<View style={styles.title}>
<Text style={styles.titleText}>{title}</Text>
</View>
{
content ? (
<View style={[styles.content, content.length > 30 ? {} : { alignItems: 'center' }]}>
<Text style={[styles.contentText, contentStyle]}>{content}</Text>
</View>
) : null
}
<View style={styles.loadAction}>
<Action text={cancelText} action={cancel}/>
{sure ? <Action text={sureText} action={sure} line/> : null}
</View>
</View>
</View>
);
EditAlert.propTypes = {
title: PropTypes.string, // 弹框标题
style: View.propTypes.style, // 弹框整体容器样式
contentStyle: Text.propTypes.style, // 内容区提示文本样式
cancel: PropTypes.func, // 取消按钮的回调函数,主要用于取消弹框的显示
cancelText: PropTypes.string, // 取消按钮展示的文字
sure: PropTypes.func, // 确认回调函数,用于处理提交的逻辑及弹框消失
sureText: PropTypes.string, // 确认按钮显示的文字
content: PropTypes.string, // 内容区展示的文案
};
EditAlert.defaultProps = {
title: 'alert',
style: {},
contentStyle: {},
cancel: () => {
},
cancelText: '取消',
sure: null,
sureText: '确认',
content: null,
};
export default EditAlert;
// 项目中使用案例
<EditAlert
title="提示"
content={alertContent}
cancel={() => this.cancel(false)}
sure={this.submit}
cancelText={'返回'}
sureText={'确认'}
contentStyle={{ color: '#f12345' }}
/>
7、按钮的实现(利用Text实现,用TouchableOpacity组件包,可以实现触摸点击事件及点击时透明度变化的效果。原生组件中的Button样式固定,不美观)
<View>
<TouchableOpacity
onPress={this.updateSubmitAlert} // 按钮点击后的功能,例如显示二次弹框或调用接口传数据
style={styles.submitBtnWrapper}
disabled={false}
accessible
>
<Text style={styles.submitTxt}> // 设置字体和文字颜色
提交
</Text>
</TouchableOpacity>
</View>
submitBtnWrapper: { // 按钮整体样式
position: 'absolute',
left: 10,
right: 10,
height: 50,
bottom: 65,
borderRadius: 5,
backgroundColor: '#82A0FA',
alignItems: 'center',
justifyContent: 'center'
},
备注:一般公司项目中会使用RN原生组件、基于原生组件封装的组件库 RNX-UI、antd-mobile组件库
React Native 版本
0.63之前
0.63-0.69