@Bios
2018-12-10T08:39:19.000000Z
字数 7485
阅读 1086
React-native app
本项目基于react ntive @0.51+ node@6.8
npm install -g react-native-cli安装SDK
先要配置jdk
直接在网上下的SDK,本打算用Android Studio但是配置了一阵各种问题,也就放弃了它。

配置环境变量
新建一个变量名:ANDROID_HOME,变量值:D:\AndroidSDK
在Path后再加一个D:\AndroidSDK\platform-tools
要将
D:\AndroidSDK\tools中的adb.exe复制到D:\AndroidSDK\platform-tools中。
配置完环境变量,打开CMD运行adb如果成功,则配置完成。
adb connect 127.0.0.1:62001 adb devices初始化一个项目:react-native init my_app
项目名不能有横线'-',可以有下划线'_'
等待几分钟就会生成一个项目,该项目已经下载好了各个依赖插件。
通过 react-native run-android,此时如果正确连接了模拟器,则会在模拟器上安装一个app。
此时还不能正常运行,需要在模拟器上打开Dev Settings -> Debug server host & port for device。
设置端口为ip:8081,例如192.168.10.209:8081.
怎样查看本机IP: 在CMD中运行
ipconfig则可以查看对应ip。

yarn add mobx mobx-react 或 npm i mobx mobx-react --save
mobx中涉及了ES7的装饰器(decorator),所以需要安装相应的插件支持。
npm i babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --save-dev 或
yarn add babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --dev
在.babelrc文件中配置babel插件:
{'presets': ['react-native'],'plugins': ['transform-decorators-legacy']}
译注:从0.44版本开始,Navigator被从react native的核心组件库中剥离到了一个名为react-native-deprecated-custom-components的单独模块中。如果你需要继续使用Navigator,则需要先npm i facebookarchive/react-native-custom-components安装,然后从这个模块中import,即import { Navigator } from ‘react-native-deprecated-custom-components’.——官网
npm i react-navigation --save
或
yarn add react-navigation
npm install react-native-vector-icons --save
或
yarn add react-native-vector-icons
安卓关联图标:在项目根目录下执行
npm i -g rnpm
rnpm link
在需要使用的地方:
import Icon from 'react-native-vector-icons/FontAwesome';
使用组件:
<Icon name="qq" size={30} color="#52C0FE"/>
遇到图标不能显示却没有报错的问题,可以删除模拟器上的app,再执行一个
react-native run-android。
如果报错信息:
原因是因为插件的SDK的platform与项目自身的不同。
修改node_modules\react-native-vector-icons\android\build.gradle
android {compileSdkVersion 23buildToolsVersion "23.0.1"defaultConfig {minSdkVersion 16targetSdkVersion 22versionCode 1versionName "1.0"}lintOptions {abortOnError false}}
再次执行react-native run-android就ok了。
const delay = timeout => {return new Promise((resolve, reject) => {setTimeout(() => reject('请求超时!'), timeout * 1000)})}/*** http请求* @param {[type]} options.url [请求地址]* @param {String} options.method [请求方法]* @param {Object} options.params [请求参数]* @param {[type]} timeout} [超时时间]* @return {[type]} [Promise]*/const httpReq = ({url,method = 'get',params = {}, timeout}) => {const paramArr = [];/*** var obj = {'a':'123','b':'345'};* console.log(Object.keys(obj)); //['a','b']*/if (Object.keys(params).length !== 0) {for (const key in params) {paramArr.push(`${key}=${params[key]}`);}}const urlStr = `${url}?${paramArr.join('&')}`; // get请求url拼接const body = paramArr.join('&'); // post请求body传参let options = {};options = {method: 'POST',headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',},body: body}if (method.toLowerCase() === 'get'){if (timeout === undefined) {return fetch(urlStr)} else {// Promise.race当数组中有一个promise返回则返回,其余的不再执行。如果超时了就不执行了return Promise.race([fetch(urlStr), delay(timeout)])}} else if (method.toLowerCase() === 'post') {if (timeout === undefined) {return fetch(url,options)} else {return Promise.race([fetch(url,options), delay(timeout)])}} else {return new Promise((resolve,reject) => {resolve('不支持该请求!');})}}export { httpReq }

将"babel-preset-react-native": "5.0.0" ----> "babel-preset-react-native": "4.0.0"
<View style={styles.productBox}><View ><Text style={{color:'#444',fontSize:16}}>{item.productName}</Text><View style={{flexDirection: 'row',alignItems: 'center',marginTop:3}}><Image source={require('../assets/higher.png')}style={{width: 33, height:20}}resizeMode = "contain"/><Text style={{marginBottom:5,color:'#fc3d14'}}>{item.productPrice}</Text></View></View><View ><Icon name="angle-right" size={30} color="#8f8888"/></View></View>const styles = StyleSheet.create({productBox: {width: width - 40,marginLeft: 20,marginTop: 20,borderRadius: 4,padding: 20,flexDirection: 'row',alignItems: 'center',justifyContent: 'space-between', // 针对view (未测试所有情形,建议用vie包裹)backgroundColor:'#fff'}})

<View><Image source={require('./assets/merchantBg_group/default_MB.png')}resizeMode = "contain"style={{width: width,marginTop:-65}}/></View>
<View style={[styles.productBox,comStyle.card]}></View>
import {Platform} from 'react-native';// 不同的平台显示不同的内容const instructions = Platform.select({ios: 'Press Cmd+R to reload,\n' +'Cmd+D or shake for dev menu',android: 'Double tap R on your keyboard to reload,\n' +'Shake or press menu button for dev menu',});type Props = {};export default class App extends Component<Props> {render() {return (<View style={styles.container}><Text style={styles.welcome}>Welcome to React Native!</Text><Text style={styles.instructions}>To get started, edit App.js</Text><Text style={styles.instructions}>{instructions} // 直接调用</Text></View>);}}
// model/goods.jsimport { observable, action } from 'mobx';import { httpReq } from '../api/httpReq.js';export default class GoodsModel {@observable goodsList = []; // 被观察者@action // 改变数据getGoodsList = async (id) => {const url = 'http://dev.xyf.78dk.com/v5/firstproductlists';const method = 'post';const params = {merchantId: id || 1005}const responseData = await httpReq({url, method, params}).then(res => res.json());this.goodsList = [].concat(responseData.data.productList);}}
// views/goods.js// 伪代码import React, { Component } from 'react';import {observer} from 'mobx-react';// 加载数据模型import GoodsModel from '../models/goods.js';import {StyleSheet,Text,View,Image,Dimensions,TouchableOpacity} from 'react-native';const {width,height} = Dimensions.get('window');import Icon from 'react-native-vector-icons/FontAwesome';@observer // 观察者export default class Goods extends Component{// new数据实例goodsModel = new GoodsModel();componentDidMount(){this.getProductList();}getProductList(){// 调用实例方法this.goodsModel.getGoodsList();}render() {// 拿取数据 (解构赋值)const { goodsList } = this.goodsModel;// 渲染let productItem = goodsList.length>0&&goodsList.map((item, index) => {return (<TouchableOpacity onPress={() => this.onPressBtn(index)} key={index}><View style={styles.productBox}><Text style={{color:'#444',fontSize:16}}>{item.productName}</Text><Text style={{color:'#444',fontSize:16}}>{item.productPrice}</Text></View></TouchableOpacity>)})return (<View><View style={{backgroundColor:"#fff"}}>……</View>{productItem}</View>);}}const styles = StyleSheet.create({……});
// nextStep.jsimport React, { Component } from 'react';import {StyleSheet,View,Text,TouchableOpacity} from 'react-native';export default class NextStep extends Component {constructor(props){super(props);}onPressBtn(){this.props.click(); // 触发父组件传递的方法}render() {return (<TouchableOpacity onPress={() => this.onPressBtn()}><View style = {styles.nextStep}><View style= {styles.btn}><Text style={styles.text}>下一步</Text></View></View></TouchableOpacity>);}}const styles = StyleSheet.create({……});
// index.jsimport React, { Component } from 'react';import {StyleSheet,Text,View,} from 'react-native';import NextStep from '../components/nextStep.js';export default class Index extends Component{componentDidMount(){this.getProductList();}// 传递到子组件的方法click(){alert(1);}render() {return (<View>……<NextStep click={() => this.click()}></NextStep></View>);}}const styles = StyleSheet.create({……});
// route/index.jsimport { StackNavigator } from 'react-navigation';// 继续增加新的页面import Goods from '../views/goods'import GoodsDetail from '../views/goods-detail'const AppNavi = StackNavigator({Goods: {screen: Goods},GoodsDetail: {screen: GoodsDetail}},{initialRouteName: 'Goods' // 初始化的页面});export default AppNavi;
// app.jsimport React, { Component } from 'react';import AppNavi from './src/routes'import {View,Text} from 'react-native';export default class App extends Component {render() {return (<AppNavi />);}}
<View style={{height: 300}}><ScrowView>.......</ScrowView></View>