React-Native牛刀小试仿京东砍啊砍砍到你手软

React-Native牛刀小试仿京东砍啊砍砍到你手软

React-Native基础教程

*React-Native基础篇做者gitjavascript

*React-Native官方文档html

*Demo前端

    几个月前facebook推出了React Native框架,容许开发着使用javascript代码来实现iOS原生的应用,随后十月份安卓版的也相继问世,今后咱们能够优雅的Learn once, write anywhere…java

    早在几年前开发者就开始使用javascript+html和PhoneGap来编写各式各样的app了,开发者能够优雅的完成一套js的shell,而后分别在不一样的平台下进行打包,最终生成不一样平台的app,知识app的最终的展示形式都是html类型的。一度曾经出现webapp 是否要取代native ,这么多年过去,结果你们也不言而知了。node

    可是react native的确是一个很了不得的东西,开发者们都不由为之欢呼,react native所展示出来的应用实质上是native应用,开发者完成同一套js代码,分别在iOS和安卓平台下分别打包最终分别能映射生成分属不一样的安卓原生应用与iOS原生应用,这个优点多是目前为止被广大开发最为喜欢的地方,一直以来web app最为你们所诟病的可能就是html的页面永远没法与原生页面的体验相比拟。react

  • 经过react native框架,你能够用JavaScript来编写和运行应用程序逻辑,而UI却能够是真正的本地代码编写的,所以,你彻底不须要一个HTML5编写的UI。ios

  • React框架采用了一种新颖的、激进的和高度函数式的方式来构建UI。简单说,应用程序的UI能够简单地用一个函数来表示应用程序当前的状态git

    React Native的重点是把React编程模型引进到移动App的开发中去。它的目的并非跨平台,一次编写处处运行。它真正的目标是“一次学习多处编写”。这是一个重大的区别。本教程只涉及iOS,但一旦你学会了它的思想,你就能够快速将一样的知识应用到Android App的编写上。github

    React Native的编写模式更加友好于从事于js的前端开发者,它自己采用了React js的模式,尤为是从事React js的开发人员,只须要熟悉下基本的文档就能瞬间变成一个iOS+安卓双向通吃的移动专家,React内部引入可一些新的概念,如 DOM和reconciliation,React直接将函数式编程的理念用到了UI层面。
不过相对来讲,OC的开发人员只要熟悉一下基本demo看上几个例子应该就不会有太多问题了,若是以前有过web端开发经验的话相信上手会更快一些。web

下面介绍一个简单的demo操做,这个教程一块儿带你去体验一下京东促销砍啊砍页面的OC->React 移植过程,经过本教程你就能够了解React Native的一些基本开发流程了。
效果:

若是你以前从未写过任何 JavaScript ,别担忧;这篇教程带着你一点一点编写代码。React 使用 CSS 属性来定义样式,这些样式一般都很易于阅读和理解,可是若是你想进一步了解,能够参考:。
要想学习更多内容,请往下看

开始

React native 关于环境搭建问题此处就很少说了,详情请见React native基础教程,此处就从咱们已经准备好一切前序工做开始,万事具有只欠东风,下面开始:

首先React Native 启动画面开始,建立helloworld工程,启动画面以下:

与此同时Xcode还会打开一个终端窗口,并显示以下信息:

这是React Navtive Packager,它在node容器中运行。你待会就会发现它的用处。
千万不要关闭这个窗口,让它一直运行在后面。若是你意外关闭它,能够在Xcode中先中止程序,再从新运行程序。

注意:

  • 在开始接触具体的代码以前(在本教程中,主要是js代码),咱们将推荐 Sublime
  • Text这个文本编辑工具,由于Xcode并不适合用于编写js代码的。固然,你也可使用 atom, brackets
  • 等其余轻量级的工具来替代。

 

React Native完成的js完成的代码实际上是跑在本地的node下面的,从appdelegate里面能够看到React Native工程会从一个本机地址“http://localhost:8081/index.ios.bundle?platform=ios&dev=true”读取一个对应的文件,这个文件中就是系统已经自动帮你打包压缩整合过之后的一个js 代码库,接下来React Native引擎会将这个库中的js代码彻底的解析、翻译成对应的iOS原生内容,最终以iOS原生UI的形式渲染到桌面上,这个就是React Native整个工做流程。

你好, React Native

在开始编写这个demo以前咱们先建立一个简单的Hello World项目,用你喜欢的文本编辑器(例如Sublime Text)打开index.ios.js ,删除全部内容。而后加入如下语句:

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  Text,
  View,
} = React;

var HelloWorld = React.createClass({
  render: function() {
    return (
      <View>
        <View><Text>你好, React Native</Text></View> 
      </View>
    );
  }
});

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

好了,“Hello World” 的演示就到此为止;接下来咱们要编写一个真正的React App了!

建立一个导航

这个demo使用了标准的UIKit中的导航控制器来提供”栈式导航体验“。接下来咱们就来实现这个功能。

在 index.ios.js, 添加如下代码:

var Home = require('./cut/Home');

var HelloWorld = React.createClass(//{
  render: function() //{
    return (
      <NavigatorIOS 
             initialRoute=//{//{title:'首页',
                        component:Home,
                      //}//}//>
    );
  //}
//});

NavigatorIOS就是React Native中对应的导航视图,咱们再次暂时能够理解就是iOS中的UINavigationController,咱们在此处建立了一个基于导航的视图控制器,rootViewController对应的页面就是Home。

建立rootView Home,添加Home.js 文件,添加代码以下:

var cutList = require('./CutList');
var Home = React.createClass({

	render:function (){
		return (
			<TouchableHighlight onPress={()=> this.goToNext()}>
			<View>
				<Text}>go to cut</Text>
			</View>
			</TouchableHighlight>
          );
	},

	goToNext:function(){
		this.props.navigator.push({
      		component: cutList,
    });
	},
});

Home 咱们只放了一个按钮,按钮文字“go to cut”,另外添加了一个点击触摸事件,事件相应题是goToNext:function(); 在函数处理事件内部,咱们只作了页面的push跳转,目标页面是cutList页面,运行效果以下:

构建砍啊砍List页面,从网络获取数据,绘制table绑定事件

构造顶部bunner动画图

轮播图这个地方采用了React Native的一个第三方库swiper(偷懒了),

var Swiper = require('react-native-swiper');
初始化数据
var sliderImgs = [
    'http://m.360buyimg.com/mobile/s725x175_jfs/t2332/80/701506039/111191/37a1273/5624850bN2469d61f.jpg',
    'http://m.360buyimg.com/mobile/s725x175_jfs/t2401/354/694665708/117887/3a283185/56248ee2N58518e76.jpg',
    'http://m.360buyimg.com/mobile/s725x175_jfs/t2506/269/651438394/152836/cf430d42/561f6b3aN80cb83f4.jpg',
    'http://m.360buyimg.com/mobilecms/s750x410_jfs/t2326/263/687562306/170970/c3f92c7/5620cbddNaa6a2cda.jpg!q70.jpg',
    'http://m.360buyimg.com/mobilecms/s750x410_jfs/t1891/237/637408747/193879/1acee0f7/5620be19N801621e4.jpg!q70.jpg'
];

//初始化UI
render:function () \\{
		return (
			<View>
				<View>
					<Swiper style=\\{styles.wrapper\\} showsButtons=\\{false\\} autoplay=\\{true\\} height=\\{150\\} showsPagination={true}>
        				<Image style={[styles.slide,]} source=></Image>
        				<Image style={[styles.slide,]} source=></Image>
        				<Image style={[styles.slide,]} source=></Image>
        				<Image style={[styles.slide,]} source=></Image>
        				<Image style={[styles.slide,]} source=></Image>
      				</Swiper>
				</View>

				<View style={styles.listViewSuper}>
					<ListView style={styles.tableStyle}
          				dataSource = {this.state.dataSource}
          				renderRow={this._renderRow.bind(this)}
                  pageSize={5}
                  automaticallyAdjustContentInsets={false}//>
				</View>
			</View>
			);
	},

再次看到render:function()这个函数,应该没那么陌生了吧,暂时能够理解render至关于ViewController中的ViewDidLoad:,咱们通常在render里面作一些初始化UI视图的工做,此处咱们初始化了swiper和ListView

swiper

  • showsButtons        (bool)   是否显示左右切换按钮(显示两个按钮左切 友切)
  • autoplay                (bool)   是否开启自动播放
  • height                    (bool)    高度(不解释)
  • showsPagination  (bool)   是否显示pageControl

ListView

  •  dataSource 绑定数据源
  •  renderRow cell绑定函数事件(等价于tableView:cellForRowAtIndexPath:)
  •  automaticallyAdjustContentInsets UI布局相关的

 

初始化数据源

getInitialState:function(){

      var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
      return {
        dataSource: new ListView.DataSource({
        	rowHasChanged: (r1, r2) => r1 !== r2
        }),
        loaded:false,
        currentPage:0,
      };
  	}

getInitialState:function()相似于OC中的init函数,咱们通常的习惯喜欢在init函数初始化一个变量等数据,在React Native依旧是这样。

发起网络请求,获取数据,缓存在全局变量List中

//定义request url 
var urlPath = 'http://ccguo.gitcafe.io/cut.json';
var CACHE = [];

//componentDidMount:function  系统方法
componentDidMount:function(){
  		this.fetchData();
  	},
//自定义函数处理网络获取数据,将数据放入全局变量CACHE
  	cache:function(items){
      for (var i in items) {
        CACHE.push(items[i]);
      }
      this.setState({
               dataSource: this.state.dataSource.cloneWithRows(CACHE),
        });
    },

//发起 网络请求,得到json
  	fetchData:function(){
      console.log('hello world');
  		fetch(urlPath)
  		  .then((response) => response.json())
        .then((responseText) => {
          console.log(responseText.cutList);
          this.cache(responseText.cutList);
        })
        .catch((error) => {
          console.log(error);
        });
  	}

    这个过程模拟了在iOS原生应用里面,初始化网络request,发起网络请求,获得数据,解析数据,而后将数据存入list这一些列操做,其实在js中,js脚本处理json的能力仍是很强的,咱们不再须要像OC中哪些objectForKey:的操做了,咱们不须要任何MJExtension、JSONModel、 Mantle等一些潜在的工具了,省去了不少的麻烦,咱们直接拿到一个json对象,直接对对象进行操做。

    另外React的网络请求此处咱们只是使用了fetch API
脸谱官方的api(脸谱对于网络请求提供了多种API,如:fetch WebSocket XMLHttpRequest等,具体可参照API)

    从代码上看js的链式编程刚看上去有点不太习惯,不过总体使用起来仍是比OC中快捷多了,foreach遍历、消息队列进出栈,总之脚步里面省去了以往还不得不在乎的好多麻烦,其实这块相对swift而言,新的版本中渐渐的已经获得了部分提高,不过仍是要感谢脸谱团队,没有他们,可能还见识不到React的强大。

构建cell

	_renderRow:function(data,sectionID,rowID){
    return (
      <TouchableHighlight onPress={() => this._pressRow(data,rowID)}>
      <View style=>
        <View style=>
          <View style=>
              <Image style= source=></Image>
          </View>
          <View style={styles.row,{flex:3,borderColor:'blue',borderWidth:0.5}}>
            <Text style=>
              {rowID+'-'+data.wname}
            </Text>
            <Text style=>京东价318.00</Text>
            <View style=>
            <Text style=>已有256人砍价</Text>
            <Text style=>立刻砍</Text>
            </View>
          </View>
        </View>
          <View style={styles.separator} />
      </View>  
      </TouchableHighlight>
      );
  },
  _pressRow: function(data,rowID) {
    this.props.navigator.push({
      component: detail,
      passProps: {data: data}
    });
  }

在上述初始化ListView UI的时间,咱们指定了renderRow 对应的action事件,此处咱们能够直接在_renderRow:function中构建本身的cell模版,至于React Native中UI的标签基本用法,你们能够去头部基础教程里面找,有点相似于html标签,总之咱们在_renderRow:function纯碎是构造cell的代码,这个相似于tableViewCell subClass, cell点击事件咱们使用一个TouchableHighlight来代替

 <TouchableHighlight onPress={() => this._pressRow(data,rowID)}>
 ....
 </TouchableHighlight>

TouchableHighlight事件处理action一样是一个函数(不解释),在_pressRow事件中咱们处理本身的cell点击跳转,顺便插一句下一步的操做,_pressRow(data,rowID)是带有形参的
另外 ListView renderRow 事件的重载函数,形参类型这个具体参照脸谱官方的api

_renderRow:function(data,sectionID,rowID)。

总体运行效果以下:

处理cell跳转事件

var detail = require('./Detail');

 _pressRow: function(data,rowID) {
    this.props.navigator.push({
      component: detail,
      passProps: {data: data}
    });
  }

React在处理事件跳转的时间,仍旧采用进栈出栈的形式,这一点和Apple的理念仍是相似的。

  • component:     参数对应将要跳转的目标页面,
  • passProps:     传参字典,内部为key-val形式,至关于一个容器,到了目标页面后能够根据key从容器中取出传递的值。

获取页面跳转时间容器中的值

<Text style={styles.view}>{this.props.data.wname}</Text> 

到了目标页面后,咱们直接从props容器直接根据key就能将传递的参数去处,此处咱们传递参数的自己是一个json,咱们只是讲wname显示到detail页面。
效果以下:

接下来作什么

恭喜你,你的第一个React Native App终于完成了!你能够在GitHub上找到每个”可运行的“步骤的项目源文件,若是你搞不定的时候它们会很是有用的 :]

若是你来自Web领域,你可能以为在代码中用JS和React框架创建基于本地化UI的App的界面并实现导航不过是小菜一碟。但若是你主要开发的是本地App,我但愿你能从中感觉到React Native的优势:快速的App迭代,现代JavaScript语法的支持和清晰的CSS样式规则。

在你的下一个App中,你是会使用这个框架,仍是会继续顽固不化地使用Swift和O-C呢?

不管你怎么选择,我都但愿你能从本文的介绍中学习到一些有趣的新东西,并把其中一些原理应用到你的下一个项目中。

若是你有任何问题及建议,请参与到下面的讨论中来!

相关文章
相关标签/搜索