-
-
Notifications
You must be signed in to change notification settings - Fork 65
Description
安装
我们推荐使用Homebrew
来安装Node
和Watchman
。在命令行中执行下列命令安装:
brew install node
brew install watchman
如果你已经安装了 Node,请检查其版本是否在 v8.3 以上。安装完 Node 后建议设置 npm 镜像以加速后面的过程(或使用科学上网工具)。
注意:不要使用 cnpm!cnpm 安装的模块路径比较奇怪,packager 不能正常识别!
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
Yarn、React Native 的命令行工具(react-native-cli)
Yarn是 Facebook 提供的替代 npm 的工具,可以加速 node 模块的下载。React Native 的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务
npm install -g yarn react-native-cli
安装完 yarn 后同理也要设置镜像源:
yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global
创建项目
使用 React Native 命令行工具来创建一个名为AwesomeProject
的新项目:
react-native init AwesomeProject
cd AwesomeProject && npm install
启动
进入ios文件夹用Xcode打开AwesomeProject.xcodeproj
文件,并启动
props
大多数组件在创建时就可以使用各种参数来进行定制。用于定制的这些参数就称为props属性。
class Greeting extends Component {
render() {
return (
<View style={{alignItems: 'center', marginTop: 50}}>
<Text>Hello {this.props.name}!</Text>
</View>
);
}
}
type Props = {};
export default class App extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome1 to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
布局
在组件样式中使用flex可以使其在可利用的空间中动态地扩张或收缩。一般而言我们会使用flex:1来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间flex值的比)。
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: 'powderblue' }} />
<View style={{ flex: 2, backgroundColor: 'skyblue' }} />
<View style={{ flex: 3, backgroundColor: 'steelblue' }} />
</View>
组件
可以新建src/components 文件夹
新建Greeting.js
,并在App.js
中引入import Greeting from './components/Greeting/Greeting.js';
,并使用<Greeting name='Eno Yao’ />
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class Greeting extends Component {
render() {
return (
<View style={{ alignItems: 'center', marginTop: 50 }}>
<Text>Hello {this.props.name}!</Text>
</View>
);
}
}
事件
点击这个按钮会调用onPress
函数,具体作用就是显示一个 alert 弹出框。
react | react-native |
---|---|
onClick | onPress |
onChange | onChangeText |
import React, { Component } from 'react';
import { Text, View, Button, Alert } from 'react-native';
export default class Greeting extends Component {
render() {
return (
<View style={{ alignItems: 'center', marginTop: 50 }}>
<Text>Hello {this.props.name}!</Text>
<Button
onPress={() => {
Alert.alert("你点击了按钮!");
}}
title="点我!"
/>
</View>
);
}
}
处理文本输入
TextInput是一个允许用户输入文本的基础组件。它有一个名为onChangeText的属性,此属性接受一个函数,而此函数会在文本变化时被调用。另外还有一个名为onSubmitEditing的属性,会在文本被提交后(用户按下软键盘上的提交键)调用。
<TextInput
style={{ height: 40 }}
placeholder="Type here to translate!"
onChangeText={(text) => this.setState({ text })}
/>
<TextInput
// style={{ height: 40 }}
placeholder="Type here to translate!"
onChangeText={this.onChangeText.bind(this)}
/>
// js
onChangeText(text) {
console.log(text)
this.setState({ text })
}
导航
在你的React Native
项目中安装react-navigation
这个包
yarn add react-navigation
# or with npm
# npm install --save react-navigation
然后,安装react-native-gesture-handler
yarn add react-native-gesture-handler
# or with npm
# npm install --save react-native-gesture-handler
Link
所有的原生依赖,这一步是必须的,之前漏了这一步在这里花费了很多时间
react-native link react-native-gesture-handler
# or
react-native link
在App.js
中把代码替换为下面这些
import React, { Component } from 'react';
import { Text, View, Button } from 'react-native';
import { createAppContainer, createStackNavigator, StackActions, NavigationActions } from 'react-navigation'; // Version can be specified in package.json
class HomeScreen extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
this.props.navigation.dispatch(StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Details' })
],
}))
}}
/>
</View>
);
}
}
class DetailsScreen extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
}
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
}, {
initialRouteName: 'Home',
});
export default createAppContainer(AppNavigator);
导航跳转
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
将路由页面封装模块化封装进组件里面
import { createAppContainer, createStackNavigator } from 'react-navigation'; // Version can be specified in package.json
import DetailsScreen from './src/components/DetailsScreen/DetailsScreen'
import HomeScreen from './src/components/HomeScreen/HomeScreen'
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
}, {
initialRouteName: 'Home',
});
export default createAppContainer(AppNavigator);
导航栏标题
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
};
}
导航栏按钮
class LogoTitle extends React.Component {
render() {
return (
<Image
source={require('../../assets/spiro.png')}
style={{ width: 30, height: 30 }}
/>
);
}
}
export default class DetailsScreen extends Component {
static navigationOptions = {
title: 'Detail',
headerTitle: <LogoTitle />,
headerRight: (
<Button
title="菜单"
onPress={() => alert('This is a button!')}
title="Info"
color="#58bc58"
/>
),
};
// other code
}
底部导航条
import { createAppContainer, createStackNavigator, createBottomTabNavigator } from 'react-navigation'; // Version can be specified in package.json
import DetailsScreen from './src/components/DetailsScreen/DetailsScreen'
import HomeScreen from './src/components/HomeScreen/HomeScreen'
import MineScreen from './src/components/MineScreen/MineScreen'
const MineNavigator = createStackNavigator({
Mine: {
screen: MineScreen,
},
Details: {
screen: DetailsScreen,
},
}, {
initialRouteName: 'Mine',
});
const HomeNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
}, {
initialRouteName: 'Home',
});
const TabNavigator = createBottomTabNavigator({
Home: HomeNavigator,
Mine: MineNavigator,
}, {
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
},
});
export default createAppContainer(TabNavigator);
网络
React Native 提供了和 web 标准一致的Fetch API,用于满足开发者访问网络的需求。如果你之前使用过XMLHttpRequest(即俗称的 ajax)或是其他的网络 API,那么 Fetch 用起来将会相当容易上手。
async componentDidMount() {
try {
let response = await fetch('https://cnodejs.org/api/v1/topics');
console.log(response.json());
} catch (error) {
console.error(error);
}
}
// or
async componentDidMount() {
var request = new XMLHttpRequest();
request.onreadystatechange = (e) => {
if (request.readyState !== 4) {
return;
}
if (request.status === 200) {
console.log('success', request.responseText);
} else {
console.warn('error');
}
};
request.open('GET', 'https://cnodejs.org/api/v1/topics');
request.send();
}
基础组件
Picker
本组件可以在iOS和Android上渲染原生的选择器Picker
import React, { Component } from 'react';
import { Text, View, Picker } from 'react-native';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
language: 'java',
itemIndex: 0,
pickers: [{
label: 'Java',
value: 'java'
}, {
label: 'JavaScript',
value: 'js'
}, {
label: 'Python',
value: 'py'
}]
};
this.setDate = this.setDate.bind(this);
}
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Picker
selectedValue={this.state.language}
style={{ height: 50, width: 100 }}
onValueChange={(itemValue, itemIndex) => this.setState({ language: itemValue, itemIndex })}>
{
this.state.pickers.map((item, index) => {
return (<Picker.Item key={index} label={item.label} value={item.value} />)
})
}
</Picker>
<Text>{this.state.language}{this.state.itemIndex}</Text>
</View>
);
}
setDate(newDate) {
this.setState({ chosenDate: newDate })
}
}
ScrollView && FlatList
能实现下拉刷新
import React, { Component } from 'react';
import { Text, ScrollView, FlatList, StyleSheet, RefreshControl } from 'react-native';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
refreshing: false,
};
}
_onRefresh = () => {
this.setState({ refreshing: true });
setTimeout(() => {
this.setState({ refreshing: false });
}, 2000)
}
render() {
return (
<ScrollView refreshControl={
<RefreshControl
title='下拉刷新'
titleColor='#58bc58'
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>} contentContainerStyle={styles.contentContainer}>
<Text style={styles.TextStyle}>1</Text>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 20,
padding: 20
},
TextStyle: {
color: 'red',
borderStyle: 'solid'
}
});
FlatList更适于长列表数据,且元素个数可以增删。和ScrollView不同的是,FlatList并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。
FlatList组件必须的两个属性是data和renderItem。data是列表的数据源,而renderItem则从数据源中逐个解析数据,然后返回一个设定好格式的组件来渲染。
import React, { Component } from 'react';
import { Text, ScrollView, FlatList, StyleSheet, RefreshControl } from 'react-native';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
refreshing: false,
data: []
};
}
async _onRefresh() {
this.setState({ refreshing: true });
var self = this;
var request = new XMLHttpRequest();
request.onreadystatechange = (e) => {
if (request.readyState !== 4) {
return;
}
if (request.status === 200) {
console.log('success', JSON.parse(request.responseText).data);
self.setState({
data: this.state.data.concat(JSON.parse(request.responseText).data)
})
self.setState({ refreshing: false });
} else {
console.warn('error');
}
};
request.open('GET', 'https://cnodejs.org/api/v1/topics');
request.send();
}
async componentDidMount() {
this._onRefresh();
}
render() {
return (
<FlatList refreshControl={
<RefreshControl
title='下拉刷新'
titleColor='#58bc58'
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>} contentContainerStyle={styles.contentContainer}
data={this.state.data}
renderItem={({ item }) => <Text style={styles.item}>{item.title}</Text>}
keyExtractor={(item) => item.id}
/>
);
}
}
const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 20,
padding: 20
},
TextStyle: {
color: 'red',
borderStyle: 'solid'
}
});
实现上拉刷新
<FlatList
onEndReached={this.onEndReached.bind(this)}
onEndReachedThreshold="0.05"
/>