您的位置:首页 > Web前端 > React

react-native入门

2016-05-08 16:36 465 查看
react-native入门

react native的强大牛逼之处就不扯了,直接进入主题,谈谈自己初次接触react native的学习经验,写一个简单的入门文档,便于总结学习知识,分享学习中遇到和解决的坑,由于我是做android开发的,因此该文主要针对android开发环境进行讲解,基于win7系统。


重点参考以下网址和书籍

React Native中文网

http://reactnative.cn/docs/0.24/getting-started.html#content

ECMAScript 6 入门

http://es6.ruanyifeng.com/#docs/destructuring

深入浅出 React Native:使用 JavaScript 构建原生应用

https://zhuanlan.zhihu.com/p/19996445

JavaScript高级程序设计(第三版)

1. 环境搭建



搭建过程参考“React Native中文网”上的讲解,这里详细说明一下android环境搭架过程。考虑到作为一名android开发人员,androidstudio以及对应的sdk等android开发环境都应该会搭架(或者自己百度android开发环境搭建),默认android环境处于搭建好的状态。

1.1.三步搞定

step1 安装Node.js

访问node.js官网:https://nodejs.org/en/,下载最新的稳定版本,这里我下载的是v4.4.4LTS,下载下来后双击安装即可。

step2 安装react-native

如果node.js已经安装好,以及对应的环境变量配置没有问题,直接运行该语句即可:npm install -g react-native-cli

step3 生成react-native开发工程

react-native init AwesomeProject


备注:AwesomeProject为你的工程名,自己随意写。



1.2.注意事项

由于众所周知的网络原因,react-native命令行从npm官方源拖代码时会遇上麻烦。请将npm仓库源替换为国内镜像,否则很有可能step3不能成功,或者耗时过长:

npm config set registry https://registry.npm.taobao.org

npm config set disturl https://npm.taobao.org/dist


react-native init一个工程的时间本来就比较长,请耐性等待(不要过早认为失败了),我在win7上init大概需要4分钟左右。



1.3.结束

是的,如果你本身就使用androidstudio进行android应用开发,这只需要这几步,就完成了react native的开发环境搭建,当然,考虑到断点调试,你还需要安装chome浏览器以及对应的插件:

React Developer Tools

https://chrome.google.com/webstore/search/react?hl=en

2.开发走起

好吧,虽然我们环境已经搭建完成,但是选用一个合适的编辑器还是很重要的,不然敲着代码都不顺心,这里我使用的webstorm,并使用对应的提示插件:https://github.com/virtoolswebplayer/ReactNative-LiveTemplate

2.1.万事俱备,开始敲代码

写一个helloworld实在太简单,只需要改改之前生成的工程的字符串就搞定了,因此就不写helloworld了,直接参考《深入浅出 React Native:使用 JavaScript 构建原生应用》这篇文章开始实践。由于在实践过程中仅仅只看了这篇文章,没有看它的源码,所以觉得自己好坑,读者遇到问题时,可以尝试看源码解决。

index,android.js

import React, {

AppRegistry,

Component,

Navigator

} from 'react-native';


import SearchPage from './js/SearchPage';


class PropertyFinder extends Component {

render() {

return (

<Navigator

initialRoute={{title: 'SearchPage',component: SearchPage}}

configureScene={(route) => {

return Navigator.SceneConfigs.VerticalDownSwipeJump;

}}

renderScene={(route, navigator) => {

let SearchPage = route.component;

return <SearchPage {...route.params} navigator={navigator} />;

}}/>

);

}

}


AppRegistry.registerComponent('PropertyFinder', () => PropertyFinder);

[/code]

这里直接使用了es6的最新语法进行编写,以前没有怎么写js代码,不过感觉这样的语法结构更容易适应,爽歪歪。

第1行

import语句后的React导入的react-native模块中的默认导出内容(export default xxx)。这里特别结实一下,刚开始没看懂这个语法。

第10行

如其名字render意思,该函数为该组件的渲染函数,渲染整个组件的显示。

第25行

组成入口组件,注意函数的第一个参数名字不能随便修改,它与android原生代码中的getMainComponentName保持一致,第二个参数名嘛,只要是一个Component就行了,名字无所谓。

2.2.重点解释Navigator

Navigator与android系统中的activity栈的作用类似。

initialRoute

它定义了Navigator的初始化组件,该组件将在应用启动时加载。

configureScene

配置界面与界面之间跳转时的动画效果

renderScene

渲染对应的组件

2.3.坑点

第19行的 {…route.params},到目前为止,我还不怎么了解它的原理,仅仅是了解它的作用(ps:刚学习,对jsx理解不深刻),这段代码定义了一个组件跳转到另一个组件时,传递对象数据的名称,后续所有的界面跳转都需要和改名字保持一致,本文使用了params,那么再进行跳转时,传递的参数名必须为params,例如:

this.props.navigator.push({

title: 'Results',

component: SearchResults,

params: {listings: response.listings}

  });

[/code]

3.布局

react-native的布局与html与css的思想保持一致,例如:html5使用html标签描述文档结构,使用css对文档表现进行渲染,而react-native使用自己的组件进行界面结构描述,使用类似于css的语法进行界面表示描述。

/**

* Created by zjh on 2016/5/5.

*/

import React, {

StyleSheet,

Text,

View,

TextInput,

TouchableHighlight,

Image,

ProgressBarAndroid,

Component

} from 'react-native';


import SearchResults from './SearchResults';


class SearchPage extends Component {

// 构造

constructor(props) {

super(props);

// 初始状态

this.state = {

searchString: 'london',

isLoading: false,

message: ''

};

  }


render() {

console.log('SearchPage.render');

var spinner = this.state.isLoading ? (<ProgressBarAndroid styleAttr="Inverse" />) : (<View/>);


return (

<View style={styles.container}>

<Text style={styles.decription}>Search for houses to buy!</Text>

<Text style={styles.decription}>Search by place-name, postcode or search near your location.</Text>

<View style={styles.flowRight}>

<TextInput

style={styles.searchInput}

value={this.state.searchString}

onChangeText={this.onSearchTextChanged.bind(this)}

placeholder='Search via name or postcode'/>


<TouchableHighlight

onPress={this.onSearchPressed.bind(this)}

style={styles.button}>

<Text style={styles.buttonText}>Go</Text>

</TouchableHighlight>

</View>


<TouchableHighlight style={styles.button} onPress={this.onLocationPressed.bind(this)} >

<Text style={styles.buttonText}>Location</Text>

</TouchableHighlight>


<Image source={require('./image/house.png')} />

{spinner}

<Text style={styles.decription}>{this.state.message}</Text>

</View>

);

}


onSearchTextChanged(text) {

console.log('onSearchTextChanged');

this.setState({searchString: text});

console.log(this.state.searchString);

}


_executeQuery(query) {

console.log(query);

this.setState({isLoading: true});


fetch(query)

.then(response => response.json())

.then(json => this._handleResponse(json.response))

.catch(error => this.setState({

    isLoading: false,

message: 'Something bad happened: ' + error

  }));

}


_handleResponse(response) {

this.setState({isLoading: false, message: ''});

if (response.application_response_code.substr(0, 1) === '1') {

//console.log('Properties found: ' + response.listings.length);

this.props.navigator.push({

title: 'Results',

component: SearchResults,

params: {listings: response.listings}

  });

} else {

this.setState({message: 'Location not recognized; please try again.'});

}

}


onSearchPressed() {

console.log('onSearchPressed');

var query = urlForQueryAndPage('place_name', this.state.searchString, 1);

this._executeQuery(query);

}


onLocationPressed() {

navigator.geolocation.getCurrentPosition(

location => {

var search = location.coords.latitude + ',' + location.coords.longitude;

this.setState({searchString: search});

var query = urlForQueryAndPage('centre_point', search, 1);

        this._executeQuery(query);

  },

error => {

this.setState({

message: 'There was a problem with obtaining your location: ' + error

});

  }

);

}

}


function urlForQueryAndPage(key, value, pageNumber) {

var data = {

country: 'uk',

pretty: '1',

encoding: 'json',

listing_type: 'buy',

action: 'search_listings',

page: pageNumber

};

data[key] = value;


var queryString = Object.keys(data)

.map(key => key + '=' + encodeURIComponent(data[key]))

.join('&');


return 'http://api.nestoria.co.uk/api?' + queryString;


}


var styles = StyleSheet.create({

decription: {

marginBottom: 20,

fontSize: 18,

textAlign: 'center',

color: '#656565'

},

container: {

padding: 30,

marginTop: 65,

alignItems: 'center'

},

flowRight: {

flexDirection: 'row',

alignItems: 'center',

alignSelf: 'stretch'

},

buttonText: {

fontSize: 18,

color: 'white',

alignSelf: 'center'

},

button: {

height: 36,

flex: 1,

flexDirection: 'row',

backgroundColor: '#48BBEC',

borderColor: '#48BBEC',

borderWidth: 1,

borderRadius: 8,

marginBottom: 10,

alignSelf: 'stretch',

justifyContent: 'center'

},

searchInput: {

height: 36,

padding: 4,

marginRight: 5,

flex: 4,

fontSize: 18,

borderWidth: 1,

borderColor: '#48BBEC',

borderRadius: 8,

color: '#48BBEC'

},

image: {

width: 217,

height: 138

}

});


export default SearchPage;

[/code]

3.1.常用布局组件与渲染熟悉

react-native提供了大量的组件,例如VIew、Text、Image等等,详细的使用方法,请参考《React Native中文网》中的内容。

3.2.坑点

虽然这里的界面渲染语法与css保持一致,比较react-native不是运行在浏览器上,因此它支持的也仅仅是一个子集而已。

flex

该属性,在进行多设备界面适配时,会使用得很多,我遇到一个坑,没有设置父组件为alignSelf: ‘stretch’,导致子组件虽然设置了alignSelf: ‘stretch’和对应的flex值,但是却没有按照比例正常显示的情况。

4.全文结束

是的,在这里就结束了,掌握的知识不多,入门确实也就是这么简单。

来自为知笔记(Wiz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: