ReactNative 例子
Table of Contents
新建项目
npm info react-native # 查看版本信息 react-native init App --version 0.51.0 # 版本号可以通过上一步得到 cd App react-native run-android
Hello World
进入项目根目录, 将 App.js 下的代码替换如下:
import React, { Component } from 'react';
import { Text } from 'react-native';
export default class HelloWorldApp extends Component {
render() {
return (
<Text>Hello world!</Text>
);
}
}
执行 react-native run-android, 打开程序, 可以看到 Hello World.
展示电影程序
场景: 从电影数据库中取得最近正在上映的 25 部电影, 并在一个 FlatList 中展示出来.
展示模拟数据
将以下代码覆盖到 App.js 文件:
import React, { Component } from 'react';
import {
AppRegistry,
Image,
StyleSheet,
Text,
View,
} from 'react-native';
var MOCKED_MOVIES_DATA = [
{title: '标题', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}},
];
export default class HelloWorldApp extends Component {
render() {
var movie = MOCKED_MOVIES_DATA[0];
return (
<View style={styles.container}>
<Text>{movie.title}</Text>
<Text>{movie.year}</Text>
<Image
source={{uri: movie.posters.thumbnail}}
style={styles.thumbnail}
/>
</View>
);
}
}
// 添加样式
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
thumbnail: {
width: 53,
height: 81,
},
});
修改样式
如果要将文字显示在图片的右边, 再放大标题, 需要修改样式.
我们增加一个 container, 实现在一个水平布局内嵌套一个垂直布局.
修改部分代码:
export default class HelloWorldApp extends Component {
render() {
var movie = MOCKED_MOVIES_DATA[0];
return (
<View style={styles.container}>
<Image
source={{uri: movie.posters.thumbnail}}
style={styles.thumbnail}
/>
<View style={styles.rightContainer}>
<Text>{movie.title}</Text>
<Text>{movie.year}</Text>
</View>
</View>
);
}
}
// 添加样式
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
thumbnail: {
width: 53,
height: 81,
},
rightContainer: {
flex: 1,
},
title: {
fontSize: 20,
marginBottom: 8,
textAlign: 'center',
},
year: {
textAlign: 'center',
},
});
拉取真正的数据
将 REQUEST_URL 常量放到 import 下面:
var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json';
初始化(放在 render() 之前):
constructor(props) {
super(props);
this.state = {
movies: null,
};
this.fetchData = this.fetchData.bind(this);
}
组件加载完毕后, 就可以向服务器请求数据了. componentDidMount() 是 React 组件的一个生命周期方法, 会在组件刚加载完成的时候调用一次, 以后不再调用.
componentDidMount() {
this.fetchData();
}
fetchData():
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
movies: responseData.movies,
});
});
}
修改 render():
render() {
if (!this.state.movies) {
return this.renderLoadingView();
}
var movie = this.state.movies[0];
return this.renderMovie(movie);
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>正在加载电影数据...</Text>
</View>
);
}
renderMovie(movie) {
return (
<View style={styles.container}>
<Image
source={{uri: movie.posters.thumbnail}}
style={styles.thumbnail}
/>
<View style={styles.rightContainer}>
<Text style={styles.title}>{movie.title}</Text>
<Text style={styles.year}>{movie.year}</Text>
</View>
</View>
);
}
FlatList
FlatList 只显示当前屏幕上的元素, 对于那些已经渲染好了, 但移动到了屏幕之外的元素, 则会从原生视图结构中移除, 以提高性能.
先在文件最开头引入 FlatList:
import {
...
FlatList,
...
} from 'react-native';
修改 render():
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<FlatList
data={this.state.data}
renderItem={this.renderMovie}
style={styles.list}
/>
);
}
修改 constructor():
constructor(props) {
super(props);
this.state = {
data: [],
loaded: false,
};
// 在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对
// 像下面这行代码一样,在constructor中使用bind是其中一种做法(还有一些其他做法,如使用箭头函数等)
this.fetchData = this.fetchData.bind(this);
}
修改 fetchData():
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
// 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作
this.setState({
data: this.state.data.concat(responseData.movies),
loaded: true,
});
});
}
添加样式:
list: {
paddingTop: 20,
backgroundColor: '#F5FCFF',
},
调试
使用 Chrome 来调试 React Native 程序
启动远程调试
摇晃手机, 点击 Debug JS Remotely.
同时会电脑会自动打开一个页面: http://localhost:8081/debugger-ui
打开 Chrome 开发者工具
按下 F12.
Sources 面板下, 可以看到 debuggerWorker.js. 将其层层打开, 可以看到我们的程序.
常见错误
Unable to load script from assets 'index.android.bundle'.
进入项目根目录:
mkdir -p android/app/src/main react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ react-native run-android
我们可以把第二条命令写到 package.json 的 "script" 字段(与 "dependencies" 字段同级)中:
"android-linux": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res && react-native run-android"
然后通过 npm run android-linux 即可.
Could not connect to development server
adb reverse tcp:8081 tcp:8081 # 如果还不行 npm start
如果提示端口占用:
sudo lsof -i :8081 kill -9 xxx
Generated by Emacs 25.x(Org mode 8.x)
Copyright © 2014 - Pinvon - Powered by EGO