一、基础
Props 属性
- 用于定制组件的参数称为属性props
- style source就是属性
- ios 上使用http连接图片不会显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| export default class Bananas extends Component { render() { let pic = { uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg' }; return ( <Image source={pic} style={{width: 193, height: 110}} /> ); } }
class Greeting extends Component { render() { return ( <View style={{alignItems: 'center'}}> <Text>Hello {this.props.name}!</Text> </View> ); } } export default class LotsOfGreetings extends Component { render() { return ( <View style={{alignItems: 'center'}}> <Greeting name='Rexxar' /> <Greeting name='Jaina' /> <Greeting name='Valeera' /> </View> ); } }
|
State 状态
- 两种数据来控制一个组件:props和state
- props是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变
- 对于需要改变的数据,我们需要使用state
1 2 3 4 5 6 7 8 9 10 11 12
| class Blink extends Component { constructor(props) { super(props); this.state = { isShowingText: true };
setInterval(() => { this.setState(previousState => { return { isShowingText: !previousState.isShowingText }; }); }, 1000); }
|
- 一切界面变化都是状态state变化
- state的修改必须通过setState()方法
- this.state.likes = 100; // 这样的直接赋值修改无效!
- setState 是一个 merge 合并操作,只修改指定属性,不影响其他属性
- setState 是异步操作,修改不会马上生效
样式
- 核心组件都接受名为style的属性,JS 的语法要求使用了驼峰命名法
- StyleSheet.create来集中定义组件的样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| export default class LotsOfStyles extends Component { render() { return ( <View> <Text style={styles.red}>just red</Text> <Text style={styles.bigblue}>just bigblue</Text> <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text> <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text> </View> ); } }
const styles = StyleSheet.create({ bigblue: { color: 'blue', fontWeight: 'bold', fontSize: 30, }, red: { color: 'red', }, });
|
高度与宽度
指定宽高
RN 中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点
1 2 3 4 5 6 7 8 9 10 11
| export default class FixedDimensionsBasics extends Component { render() { return ( <View> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} /> <View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} /> </View> ); } }
|
弹性(Flex)宽高
- flex:1来指定某个组件扩张以撑满所有剩余的空间
- 有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间
- 这些并列的子组件的flex值不一样,则谁的值更大,谁占据剩余空间的比例就更大
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| export default class FlexDimensionsBasics extends Component { render() { return ( <View style={{flex: 1}}> <View style={{flex: 1, backgroundColor: 'powderblue'}} /> <View style={{flex: 2, backgroundColor: 'skyblue'}} /> <View style={{flex: 3, backgroundColor: 'steelblue'}} /> </View> ); } }
|
使用Flexbox布局
- 使用 flexDirection alignItems justifyContent 三个样式属性就已经能满足大多数布局需求
flexDirection 布局的主轴
1 2
| style={{flexDirection: 'row' }} 水平轴 style={{flexDirection: 'column' }} 竖直轴 默认
|
1 2 3 4 5
| <View style={{flex: 1, flexDirection: 'row'}}> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} /> </View>
|
justifyContent 排列方式
flex-start、center、flex-end、space-around、space-between以及space-evenly
1 2 3 4 5 6 7 8 9
| <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', }}> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} /> </View>
|
alignItems 决定其子元素沿着次轴的排列方式
flex-start、center、flex-end以及stretch
1 2 3 4 5 6 7 8 9 10
| <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'stretch', }}> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{height: 50, backgroundColor: 'skyblue'}} /> <View style={{height: 100, backgroundColor: 'steelblue'}} /> </View>
|
处理文本输入 TextInput
- onChangeText 函数会在文本变化时被调用
- onSubmitEditing的属性,会在文本被提交后(用户按下软键盘上的提交键)调用
1 2 3 4 5 6 7 8 9 10
| <View style={{padding: 10}}> <TextInput style={{height: 40}} placeholder="Type here to translate!" onChangeText={(text) => this.setState({text})} /> <Text style={{padding: 10, fontSize: 42}}> {this.state.text.split(' ').map((word) => word && '🍕').join(' ')} </Text> </View>
|
处理触摸事件
显示一个简单的按钮
Button是一个简单的跨平台的按钮组件
1 2 3 4 5 6
| <Button onPress={() => { Alert.alert("你点击了按钮!"); }} title="点我!" />
|
Touchable 系列组件
- ScrollView是一个通用的可滚动的容器
- 通过horizontal属性来设置
- 适合用来显示数量不多的滚动元素
1 2 3 4 5 6 7 8 9
| export default class IScrolledDownAndWhatHappenedNextShockedMe extends Component { render() { return ( <ScrollView> </ScrollView> ); } }
|
- 适用于展示长列表数据的组件
- 和ScrollView不同的是,FlatList并不立即渲染所有元素,而是优先渲染屏幕上可见的元素
- 必须的两个属性是data和renderItem。data是列表的数据源,而renderItem则从数据源中逐个解析数据,然后返回一个设定好格式的组件来渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| export default class FlatListBasics extends Component { render() { return ( <View style={styles.container}> <FlatList data={[ {key: 'Devin'}, {key: 'Jackson'}, {key: 'James'}, {key: 'Joel'}, {key: 'John'}, {key: 'Jillian'}, {key: 'Jimmy'}, {key: 'Julie'}, ]} renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>} /> </View> ); } }
|
要渲染的是一组需要分组的数据,也许还带有分组标签的,那么SectionList将是个不错的选择
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| export default class SectionListBasics extends Component { render() { return ( <View style={styles.container}> <SectionList sections={[ {title: 'D', data: ['Devin']}, {title: 'J', data: ['Jackson', 'James', 'Jillian', 'Jimmy', 'Joel', 'John', 'Julie']}, ]} renderItem={({item}) => <Text style={styles.item}>{item}</Text>} renderSectionHeader={({section}) => <Text style={styles.sectionHeader}>{section.title}</Text>} keyExtractor={(item, index) => index} /> </View> ); } }
|
网络
使用Fetch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| fetch("https://mywebsite.com/endpoint/", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ firstParam: "yourValue", secondParam: "yourOtherValue" }) });
export default class FetchExample extends React.Component {
constructor(props){ super(props); this.state ={ isLoading: true} }
componentDidMount(){ return fetch('https://facebook.github.io/react-native/movies.json') .then((response) => response.json()) .then((responseJson) => {
this.setState({ isLoading: false, dataSource: responseJson.movies, }, function(){
});
}) .catch((error) =>{ console.error(error); }); }
|
WebSocket 支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var ws = new WebSocket("ws://host.com/path");
ws.onopen = () => { ws.send("something"); };
ws.onmessage = e => { console.log(e.data); };
ws.onerror = e => { console.log(e.message); };
ws.onclose = e => { console.log(e.code, e.reason); };
|
二、进阶
组件和API
基础组件
View Text Image TextInput ScrollView StyleSheet
交互控件
Button Picker Slider Switch
列表视图
FlatList 高性能滚动列表
SectionList 比前者多了分组
React Native 提供了一个检测当前运行平台的模块。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import { Platform, StyleSheet } from "react-native";
const styles = StyleSheet.create({ height: Platform.OS === "ios" ? 200 : 100 }); const styles = StyleSheet.create({ container: { flex: 1, ...Platform.select({ ios: { backgroundColor: "red" }, android: { backgroundColor: "blue" } }) } });
const Component = Platform.select({ ios: () => require("ComponentIOS"), android: () => require("ComponentAndroid") })();
<Component />;
|
使用导航器跳转页面
- 只针对 iOS 平台开发 可以选择NavigatorIOS
- 同时在iOS和Android上达到看起来像原生 原生导航: react-native-navigation
图片
静态图片资源
1 2 3
| <Image source={require('./my-icon.png')} />
|
静态的非图片资源
require语法也可以用来静态地加载你项目中的声音、视频或者文档文件。大多数常见文件类型都支持,包括.mp3, .wav, .mp4, .mov, .htm 和 .pdf等
使用混合 App 的图片资源
- 编写一个混合 App,原生+RN ,放置在 Xcode 的 asset 类目中,或是放置在 Android 的 drawable 目录里。
- 注意此时只使用文件名,不带路径也不带后缀
1 2 3 4
| <Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />
<Image source={{uri: 'asset:/app_icon.png'}} style={{width: 40, height: 40}} />
|
网络图片
需要手动指定图片的尺寸
1 2 3 4 5 6
| <Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}} style={{width: 400, height: 400}} />
<Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}} />
|
动画
React Native 提供了两个互补的动画系统:用于创建精细的交互控制的动画Animated和用于全局的布局动画LayoutAnimation