React-Native基础教程

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

React-Native基础教程

*React-Native基础篇作者git

*React-Native官方文档

*Demo

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

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

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

  • 通过react native框架,你可以用JavaScript来编写和运行应用程序逻辑,而UI却可以是真正的本地代码编写的,因此,你完全不需要一个HTML5编写的UI。
  • React框架采用了一种新颖的、激进的和高度函数式的方式来构建UI。简单说,应用程序的UI可以简单地用一个函数来表示应用程序当前的状态

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

React Native的编写模式更加友好于从事于js的前端开发者,它本身采用了React js的模式,尤其是从事React js的开发人员,只需要熟悉下基本的文档就能瞬间变成一个iOS+安卓双向通吃的移动专家,React内部引入可一些新的概念,如 DOM和reconciliation,React直接将函数式编程的理念用到了UI层面。
不过相对来说,OC的开发人员只要熟悉一下基本demo看上几个例子应该就不会有太多问题了,如果之前有过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 ,删除所有内容。然后加入以下语句:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

‘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, 添加以下代码:


1

2

3

4

5

6

7

8

9

10

11

12

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 文件,添加代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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(偷懒了),


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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布局相关的

初始化数据源


1

2

3

4

5

6

7

8

9

10

11

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中


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

//定义request url

var urlPath = http://ccguo.gitcafe.io/cut.json;

var CACHE = [];

//componentDidMount:function  系统方法

componentDidMount:function(){

        this.fetchData();

    },

//自定义函数处理网络获取数据,将数据放入全局变量CACHE

    cache:function(items){

      for (var 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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

  _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来代替


1

2

3

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

....

</TouchableHighlight>

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

_renderRow:function(data,sectionID,rowID)。

整体运行效果如下:

处理cell跳转事件


1

2

3

4

5

6

7

8

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呢?

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

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

分类: iOSObjective - C

时间: 2024-10-06 19:50:45

React-Native基础教程的相关文章

React Native基础&amp;入门教程:初步使用Flexbox布局

在上篇中,笔者分享了部分安装并调试React Native应用过程里的一点经验,如果还没有看过的同学请点击<React Native基础&入门教程:调试React Native应用的一小步>. 在本篇里,让我们一起来了解一下,什么是Flexbox布局,以及如何使用. 一.长度的单位 在开始任何布局之前,让我们来首先需要知道,在写React Native组件样式时,长度的不带单位的,它表示“与设备像素密度无关的逻辑像素点”. 这个怎么理解呢? 我们知道,屏幕上一个发光的最小点,对应着一个

菜鸟窝React Native 系列教程-1.移动端开发趋势与未来

菜鸟窝React Native 系列教程-1.移动端开发趋势与未来 课程持续更新中..... 我是RichardCao,现任新美大酒店旅游事业群的Android Developer.如果你也有兴趣录制RN视频,请加入下面QQ群找我. 下载地址:https://pan.baidu.com/s/1c1XmE56 密码:shhw 首发地址:菜鸟窝-ReactNative学习板块 交流QQ群:576089067 课程目录:菜鸟窝React Native 系列教程

【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框&&获取组件实例常用的两种方式

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2346.html 本篇Himi来利用ListView和TextInput这两种组件实现对话.聊天框. 首先需要准备的有几点:(组件的学习就不赘述了,简单且官方有文档) 1. 学习下 ListView: 官方示例:http://reactnative.cn/docs/0.27/tutorial.html#content

【REACT NATIVE 系列教程之二】创建自定义组件&&导入与使用示例

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2219.html 在上一篇  [REACT NATIVE 系列教程之一]触摸事件的两种形式与四种TOUCHABLE组件详解 中的最后介绍了如何使用Touchable的四种组件进行监听触摸事件.  那么紧接着我们利用Touchable来包装一个带图片的Button组件,且设计成可接受很多自定义参数. 一:创建我们自定义

【REACT NATIVE 系列教程之十二】REACT NATIVE(JS/ES)与IOS(OBJECT-C)交互通信

一用到跨平台的引擎必然要有引擎与各平台原生进行交互通信的需要.那么Himi先讲解React Native与iOS之间的通信交互. 本篇主要分为两部分讲解:(关于其中讲解的OC语法等不介绍,不懂的请自行学习) 1. React Native 访问iOS 2. iOS访问React Native     一:React Native 访问iOS 1. 我们想要JS调用OC函数,就要实现一个"RCTBridgeModule"协议的Objective-C类 所以首先我们先创建一个oc新类,  

【REACT NATIVE 系列教程之十一】插件的安装、使用与更新(示例:REACT-NATIVE-TAB-NAVIGATOR)

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2294.html 本篇主要来详细介绍如何安装.升级插件及讲解一个react-native-tab-navigator的示例. 首先推荐一个插件网站:https://www.npmjs.com     (此插件属于半官方维护的) 本文举例使用的插件:react-native-tab-navigator ,选项卡形式的导

【REACT NATIVE 系列教程之七】统一ANDROID与IOS两个平台的程序入口&&区分平台的组件简介

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2260.html       本篇介绍两个细节:       1. 关于如何将index.android.js 与index.ios.js统一管理起来.       2.  Platform 组件的简单介绍与使用   一:将index.android.js 与index.ios.js统一管理起来. 由于React本身

React Native基础&amp;入门教程:调试React Native应用的一小步

React Native(以下简称RN)为传统前端开发者打开了一扇新的大门.其中,使用浏览器的调试工具去Debug移动端的代码,无疑是最吸引开发人员的特性之一. 试想一下,当你在手机屏幕按下一个按钮,处理事件的代码就可以立即在浏览器的调试工具里进行断点调试,而且每当你对代码进行修改,界面便可以完成快速地重载,省去昂长的编译时间,这会是多么提高工作效率. 传统的Web前端开发人员自然很熟悉浏览器的调试工具,但是对于如何将其在RN中使用以便和移动端结合起来,也许会相当陌生.这也成为了一些开发者跨入R

【REACT NATIVE 系列教程之五】NAVIGATOR(页面导航)的基本使用与传参

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2248.html 今天介绍一种应用开发中常用的负责页面切换及导航功能的组件:Navigator 一:Navigator 对于页面导航其实主要功能就是:每个页面都知道本身应该切换到哪个页面,并且切到的页面会记录从哪里来,如果要返回的话,知道返回到哪个页面.这一切都不需要再用逻辑管理!而且每个页面之间也可以进行参数传递,

【REACT NATIVE 系列教程之一】触摸事件的两种形式与四种TOUCHABLE组件详解

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2203.html 本文是RN(React Native)系列教程第一篇,当然也要给自己的群做个广告:   React Native @Himi :126100395  刚创建的群,欢迎一起学习.讨论.进步. 本文主要讲解两点: 1.   PanResponder:触摸事件,用以获取用户手指所在屏幕的坐标(x,y)或触