1.定义类的协议一般是这样的结构
interface IProps {
propA: any,
propB: any
}
interface IState {
stateA: any,
stateB: any
}
export default class ClaseName extends Component<IProps, IState> {}
ts语法中,这样定义之后,就可以在类中通过this.props.propA以及this.state.stateA来引用值,并且会有代码提示
如果你的类中不需要用到
props,只用到state的话,写成export default class ClaseName extends Component<IState>这样的话,在类中调用this.state.stateA,在使用ESLint时,会有报错提示,换成export default class ClaseName extends Component<{},IState>即可。查看Component定义:interface Component<P = {}, S = {}, SS = any>,可发现有P S SS三种协议,虽然不知道原因,但可以猜测P代表的是Props,S代表的是State,然后自己定义的IProps IState分别对应的P S,所以只有State时不定义Props会导致类不认识IState里定义的参数,导致报错。
2.动态获取屏幕宽高,状态栏(statusBar)高度
import { NativeModules, Platform, StatusBar, Dimensions } from 'react-native';
// 获取状态栏高度
let oStatusHeight = 0;
function getStatusHeight(callback?: (height: number) => void) {
if (oStatusHeight) {
callback && callback(oStatusHeight);
return;
}
if (Platform.OS === 'ios') {
const { StatusBarManager } = NativeModules;
// iOS Only
if (StatusBarManager && StatusBarManager.getHeight) {
StatusBarManager.getHeight((statusBar: { height: number }) => {
const { height } = statusBar;
oStatusHeight = height;
callback && callback(oStatusHeight);
});
}
} else {
const { currentHeight } = StatusBar;
oStatusHeight = currentHeight || 0;
callback && callback(oStatusHeight);
}
}
// 在这里执行一次,是因为获取状态栏高度为异步获取,所以导致不能及时获取到高度,提前调用一下可以在使用之前就已经给`oStatusHeight`赋好值,就不会出现获取失败的情况了
getStatusHeight();
// Dimensions.get('window')获取的是手机中代码可控的区域,
// Dimensions.get('screen')获取的是真正的屏幕尺寸,包括一些代码不可控制的区域(例如安卓手机的状态栏,还有底部的操作栏)
const screen = Dimensions.get('window');
const screenWidth = screen.width;
const screenHeight = screen.height;
3.货币格式化,更多的货币格式化可以研究Intl工具,很强大
// 格式化货币,传入的货币以分为单位,eg: formatMoney(1) = ¥0.01, formatMoney(13644) = ¥136.44, formatMoney(122244) = ¥1,222.44
formatMoney(amount: number | string): string {
const amoutNumber = Number(amount);
if (amoutNumber === 0) {
return '0';
}
const formater = Intl.NumberFormat('zh-Hans-CN', {
style: 'currency',
currency: 'CNY',
useGrouping: true // 数字超过1000会加,分隔
});
return formater.format(amoutNumber / 100);
}
4.Component支持多个style样式的方法
Component的style可以使用数组赋值,即拥有一个样式的集合。
<View style={[viewStyle.styleOne, viewStyle.styleTwo]} />
const viewStyle = StyleSheet.create({
styleOne: {
flex: 1,
backgroundColor: 'red',
marginTop: 5,
marginBottom: 10
},
styleTwo: {
backgroundColor: 'green',
marginLeft: 20
}
}
代码中View设置了两个样式viewStyle.styleOne和viewStyle.styleTwo,既然是数组,那么就是有序的,viewStyle.styleTwo中的属性会覆盖viewStyle.styleOne中相同的属性,同时添加新的属性
5.使用TouchableOpacity包裹View或Text等来实现点击效果,不使用Button
不使用Button的原因是因为Button无法改变标题字体,颜色之类的,样式不灵活。
6.SectionList的一些使用记录
直接上代码:
// 注意这里赋值给SectionList的sections数据源一定要是这样的结构
const tempArr = [{ data: [ any ] }, { data: [ any ]}];
<SectionList
style={{ flex: 1 }}
renderItem={this._renderItem}
renderSectionHeader={this._renderSectionHeader}
keyExtractor={(item, _) => item.id}
ListHeaderComponent={this._renderListHeader}
ListFooterComponent={this._renderListFooter}
onScroll={this.onScroll}
sections={tempArr}
stickySectionHeadersEnabled={true}
/>
// 注意这里的item,一定要用item才能正确的解析到SectionList中sections对应的数据
_renderItem = ({ item }: { item: LabelDetailContentItem }) => {
return <LabelDetailCell itemData={item} />;
};
SectionList的renderSectionHeader在iOS中自带吸顶效果,在安卓中需要设置stickySectionHeadersEnabled为true才有同样的吸顶效果。
ListHeaderComponent和ListFooterComponent分别是整个SectionList的头和尾,头可以用来做下拉刷新等功能,而尾可以用来做加载更多等功能。
7.项目中自己写的一个时间戳转化为时间的工具方法
/** 学习笔记:
* 获取当前时间:now = new Date();
* 获取当前月份的时候需要+1(获取的月份为0~11)
* 通过 now.getDate() 才是获取当前日(几月几日的日), now.getDay()获取的是周几
*/
export default class DateTools {
public static formatTimeStamp(timeStamp: number): string {
const nowDate = new Date();
const nowDateTimeStamp = nowDate.getTime();
console.log(nowDateTimeStamp);
if (nowDateTimeStamp < timeStamp) {
return '';
}
const tempDate = new Date(timeStamp);
const tempYear = tempDate.getFullYear();
const tempMonth = tempDate.getMonth() + 1;
const tempDay = tempDate.getDate();
const tempHours = tempDate.getHours();
const tempMinutes = tempDate.getMinutes();
const yearString = `${tempYear}`;
const monthString = tempMonth < 10 ? `0${tempMonth}` : `${tempMonth}`;
const dayString = tempDay < 10 ? `0${tempDay}` : `${tempDay}`;
const hoursString = tempHours < 10 ? `0${tempHours}` : `${tempHours}`;
const minutesString =
tempMinutes < 10 ? `0${tempMinutes}` : `${tempMinutes}`;
const yearDif = nowDate.getFullYear() - tempYear;
const dayDif = DateTools.getDayBetweenDate(nowDateTimeStamp, timeStamp);
const hourDif = DateTools.getHoursBetweenDate(
nowDateTimeStamp,
timeStamp
);
const minuteDif = DateTools.getMinutesBetweenDate(
nowDateTimeStamp,
timeStamp
);
if (yearDif >= 1) {
return `${yearString}年${monthString}月${dayString}日`;
} else if (dayDif > 1) {
return `${monthString}月${dayString}日`;
} else if (dayDif === 1) {
return `昨天 ${hoursString}:${minutesString}`;
} else if (hourDif >= 1) {
return `${hoursString}:${minutesString}`;
} else if (minuteDif >= 1) {
return `${minuteDif}分钟前`;
} else {
return '刚刚';
}
}
private static getDayBetweenDate(
timeStamp: number,
otherTimeStamp: number
): number {
return Math.floor((timeStamp - otherTimeStamp) / 1000 / 60 / 60 / 24);
}
private static getHoursBetweenDate(
timeStamp: number,
otherTimeStamp: number
): number {
return Math.floor((timeStamp - otherTimeStamp) / 1000 / 60 / 60);
}
private static getMinutesBetweenDate(
timeStamp: number,
otherTimeStamp: number
): number {
return Math.floor((timeStamp - otherTimeStamp) / 1000 / 60);
}
}
8.string 转 number
string转number有两种方法: (1)parseInt()parseFloat()(2)Number()区别:
parseInt()、parseFloat()转换第一个无效字符之前的字符串,例如parseInt(1.2.3)为1,parseFloat(1.2.3)为1.2;Number()如果是不能转换的字符串则输出NaN,例如Number(1.2.3)为NaN,如果字符串能被转换成number类型,则Number()函数将判断调用parseInt()还是parseFloat()函数转换。