用文章和视频的app例子简介React-Native

来源:互联网 发布:ntfs for mac序列号 编辑:程序博客网 时间:2024/06/01 08:14

转自:http://www.ibm.com/developerworks/cn/mobile/mo-bluemix-react-native-ios8/index.html

如有侵犯,请来信oiken@qq.com


发布取得极大成功的 React JavaScript 开源 UI 库两年后,Facebook/Instagram 在 2015 年 5 月的 F8 大会期间引起了另一场轰动。令充满艳羡的全球开发人员社区(包括旧 React 兄弟产品的坚定支持者)高兴的是,开源的 React Native 项目迅速在 GitHub 上流行起来。在短短的 3 个月内,React Native 获得了超过 170 个全球贡献者的支持,获得了超过 15,000 位明星的支持。什么令人震惊的功能能换来如此热情的欢迎?简言之:JavaScript 中超级容易的 iOS 应用程序开发。React Native 完成并超越这一目标,使它成为自 iOS 诞生以来发展最快的开发平台和工具。

本教程将介绍 React Native 并解释它的架构和内部操作。您将完成一个完整的应用程序示例,该示例突出了重要的 React Native 开发技术。文中还提供了可用于 React Native 的工具的简要概述。您需要熟悉 React 编程才能掌握 React Native 的精髓;本教程假设您熟悉 React 编程。充满积极性的 JavaScript 开发人员可通过一个下午轻松地学习两种库。相对而言,正式加入传统的 iOS 开发通常会花几个月,通常需要花几个星期来掌握古老的 Objective-C(或新的 Swift)编程语言,理解特定于 iOS 的布局和 UI 构建技术和工具,掌握复杂的 Xcode IDE 的精髓,并熟悉一种多方面的构建工作流。

结合使用 IBM MobileFirst 和 React Native 应用程序

一定要阅读我的教程 “使用 React Native 和 Advanced Mobile Access 编写 iOS 8 游戏”,了解如何使用 IBM Bluemix 上的 MobileFirst 平台所提供的丰富服务来轻松地增强您的 React Native 应用程序。

阅读:React:创建可维护、高性能的 UI 组件

阅读:使用 React 创建 IBM Watson 资源管理器

React Native 内幕探秘

React Native 针对移动开发改写了 React(已是一个得到数万忠诚的 JavaScript 开发人员使用的成熟的库)的最优秀特性。借助 React,您可以通过高性能、可重用的组件构建应用程序,设计这些精益的组件。React 通过将 Web 开发人员与浏览器的怪异 DOM 相隔离来提高性能 — 通过虚拟 DOM 的概念。您的 React 代码修改了虚拟 DOM,React 运行时负责优化物理 DOM 的刷新和更新。

React Native 架构

在 React Native 中,您还可以修改一个虚拟 DOM 来编程。但不同于 React,这个 DOM 没有物理浏览器提供支持。相反,虚拟 DOM 的目标渲染输出由真实的原生 iOS UI 组件组成。

所有这些魔力都通过一个优化的异步 来实现的。图 1 演示了 React Native 的运行时架构。

图 1. React Native 的高级运行时架构
该图演示了 React Native 的运行时架构

在这个灵活的架构中,JavaScript 解释器可以在任何地方运行。通常,解释器在设备或模拟器上的原生应用程序内的一个线程上运行。但是,在远程调试期间,JavaScript 代码可在开发人员的浏览器中运行(参见 “强大的工具、即时满足” 小节)。图像编码、磁盘 I/O 和布局等耗时的任务,可以移交给其他工作线程,充分利用现代移动设备上的多核 CPU 所提供的并行性。

为原生 iOS 平台组件提供补充

React Native 的编程模型将会尽可能隐藏您没有在浏览器中运行代码的事实。但是,标准 HTML 组件所拥有的许多特性和属性在原生 iOS 平台 UI 组件上不可用(反之亦然)。所以在使用 React Native 编程时,只能使用标准属性的一个子集。(参阅 React Native API 文档,了解有关的详细信息。) 

ES6 JavaScript 语法

您可能在示例应用程序的源代码中注意到,JavaScript 语法看起来与您通常使用的语法稍有不同。原因在于 React Native 工具集包含 Babel JavaScript 编译器。Babel 同时支持 JSX 语法和即将推出的 ECMAScript 6 (ES6) 语法,而且编译为 ES5。ES5 自 2009 年 12 月开始成为 JavaScript 标准,目前受所有现代浏览器和服务器端 JavaScript 引擎支持。

不同于 DOM 组件,iOS UI 组件不会响应 CSS 样式。因为这个原因,React Native 通过 JavaScript StyleSheet 对象而不是 CSS 来执行所有样式。但是,React Native 支持一种人们所熟悉的类似 CSS 的语法,该语法提供了部分人们熟悉的 CSS 属性选择器。

iOS 应用程序中的用户输入事件处理与典型 Web 应用程序有明显不同。React Native 提供了一个依据 iOS 自己的手势响应系统而建模的全面的 Gesture Responder 系统。如果有必要,应用程序可以调整 Gesture Responder,通过组件层获得对事件传播和自定义升级的细粒度控制。

最后但同样重要的是,使用 Objective-C/Swift 的典型移动开发人员能够获得对底层平台 API 的丰富支持 — 从相机控制到网络访问,再到电话联系人管理。React Native 无法支持所有这些特性,仍然保持简洁。相反,React Native 架构中心的异步桥支持任意 Objective-C API 到 JavaScript 的双向导出。这种设计使 React Native 团队(以及更大的 React Native 开发人员社区)能够逐步迁移平台特性和 API。

React Native 示例应用程序分析

本教程的示例是一个文档和视频查看器应用程序。在启动该应用程序时,初始屏幕将会显示一个可滚动的文章列表,如图 2 所示。

图 2. 应用程序显示的可选择的文章列表
示例应用程序的初始屏幕的屏幕截图

如果选择一篇文章,这篇文章就会显示在 Web 视图中供阅读,如图 3 所示。

图 3. 选择阅读的文章
应用程序的文章视图的屏幕截图

您可以触摸左上角的 Articles 链接返回到文章列表。触摸 Videos 可以查看可用的开源视频列表,如图 4 所示。

图 4. 应用程序显示了可用视频列表
可用视频列表的屏幕截图

选择任何视频即可在一个新视频视图中开始播放它,如图 5 所示。

图 5. 应用程序播放开源的 Elephants Dream 影片

您可以随时触摸左上角的 Videos 链接停止视频回放,返回到视频列表。

图 6 显示了此应用程序中的故事板屏幕流。从显示文章的主屏幕中,您可以导航到视频列表,或者选择一篇文章,在 Web 视图中显示它。从视频列表,您可以选择一个视频来开始播放它,或者返回到文章列表。在这些屏幕背后,一个 <NavigationIOS> 组件是故事板流的编排器(参阅 “使用 <NavigatorIOS> 组件编排视图” 小节)。

图 6. dwviewer 应用程序的故事板流
示例应用程序的故事板流的图

安装 React Native 和运行示例应用程序

Apple 要求在 Mac 上执行所有 iOS 开发。您需要在 Mac 上安装一个最新的 Xcode 版本来处理 iOS 应用程序,包括您使用 React Native 构建的应用程序。确保您在已满足这个 入门指南 中的所有要求的 Mac 上。另外,按照指南,通过以下命令安装 React Native:

npm install -g react-native-cli

在项目目录中,运行:

npm install

React Native 有一个生成器创建了一个可以自定义的有效的骨架样板应用程序。您需要的所有工具都集成在应用程序中,您只需要打开它的 .xcodeproj 文件并在 Xcode 中运行它。Xcode 构建该应用程序,启动一个 PC 到模拟器/设备的桥接打包服务器,然后在 iOS 模拟器(或真实设备)上启动该应用程序。

下载 教程的示例代码,其中包含已完成的 dwviewer 应用程序。在根目录上运行 npm install,然后通过以下命令打开 Xcode 项目文件:

open dwviewer.xcodeproj

然后单击 Xcode 中的 run 来构建该项目,在一个 shell 中启动打包服务器,然后在模拟器中启动该应用程序。该应用程序将会显示如 图 2 所示的初始屏幕。

一旦 React Native 应用程序在模拟器中运行,您就可以按下一个热键来触发通过打包服务器对 JavaScript 代码的重新加载。(当应用程序在设备上运行时,摇晃设备具有相同的效果。)打包服务器也会定期扫描项目目录中的 JavaScript 源代码更改,在您编码过程中向您提醒任何编译错误。Xcode 的应用程序分析器自动启动,所以您可以在应用程序在模拟器中运行时实时监视它的内存和 CPU 需求。

深入分析代码

可以在 index.ios.js 文件中找到示例应用程序的所有代码。一个补充性的 datasource.js 文件为应用程序提供了数据。

放置一个 article-list 单元

作为 React 用户,您会发现代码的结构让您感到很熟悉。除了 JavaScript 代码(参阅 ES6 JavaScript 语法 边栏)之外,您还会看到使用 JSX 语法的 render() 调用。清单 1 中的代码定义了一个 article-list 单元。

清单 1. 一个 article-list 单元的定义
renderArticle: function(article) {  return (    <TouchableOpacity     activeOpacity={0.5}     onPress={() => this.showArticle(article.url)}>     <View style={styles.cellcontainer}>       <View style={styles.celltitlerow}>         <Text style={styles.title}>{article.title}</Text>         <Text style={styles.year}>({article.year})</Text>       </View>       <Text style={styles.description}>{article.desc}</Text>     </View>    </TouchableOpacity>    );},

article-list 单元是 <TouchableOpacity><View> 和 <Text> 组件的组合。 

使用 <TouchableOpacity> 即时响应触摸

FlexBox polyfill

如果您像大多数 React Native 开发人员一样,最初参与了 Web 应用程序开发并熟悉 CSS Flexible Box Layout。iOS 原生 UI 组件不支持 CSS FlexBox,但大部分典型的 iOS 应用程序布局都可完全使用 FlexBox 来指定。React Native 通过其 StyleSheet 对象实现中的一个 polyfill 来支持 FlexBox Layout 模型。得益于 polyfill,经验丰富的 Web 开发人员能够非常轻松地使用 FlexBox 来布局 iOS UI 屏幕。其他可用的 polyfill 包括 requestAnimationFrame、XMLHttpRequest 和 fetch。

<TouchableOpacity> 组件包装 laid-out 单元,并在用户触摸该单元时提供一个不透明性更改反馈动画,该动画完全由原生组件处理。这种实时反馈是原生 iOS 应用程序与在移动设备上运行的 Web 应用程序的一大区别。activeOpacity 特性指定在触摸单元时要使用的不透明性(半透明或完全不透明)。<TouchableOpacity> 组件还通过 onPress 处理函数转发事件(一个 React 合成 事件)。在本例中,ArticleView 自己的 showArticle() 方法是通过文章的 URL 调用的。React Native 还拥有 <TouchableHighlight> 组件来对用户触摸包装的组件时的即时反馈效果进行进一步控制。

通过 JavaScript StyleSheet API 和 FlexBox 设置组件的样式

在 清单 1 中,请注意,我们使用了 style={styles.*} 来设置各种组件的样式。React Native 使用一个支持 FlexBox 布局的 JavaScript StyleSheet API(参阅 FlexBox polyfill 边栏)。

该应用程序的样式在清单 2 中的代码中定义。

清单 2. 样式定义
var styles = StyleSheet.create({ ...  cellcontainer: {    flex: 1,    flexDirection: 'column',    justifyContent: 'center',    alignItems: 'stretch',    backgroundColor: '#F5FCFF',    borderWidth: 0.5,    borderColor: '#d6d7da',    padding: 5,  },  celltitlerow: {    flex: 1,    flexDirection: 'row',    justifyContent: 'flex-start',    alignItems: 'stretch',    backgroundColor: '#F5FCFF',  },...});

在清单 2 中,您可以看到类似 CSS 的熟悉的选择器(出于 JavaScript 兼容性考虑,使用了驼峰样式取代带连字符的选择器名称)和 FlexBox 布局选项。

使用 <NavigatorIOS> 组件编排视图

触摸一个文章单元时,会调用 showTouch() 方法,该文章会使用一个 <Webview> 组件来显示:

showArticle: function(articleURL) {    this.props.navigator.push({      title: "Article",      component: WebView,       passProps: {url: articleURL},    });  },

<WebView> 组件在一个可配置的微型浏览器中显示选定的文章。<WebView> 由一个 <NavigatorIOS> 组件以动画方式从右侧进入,该组件可通过 navigator 特性进行引用。<NavigatorIOS> 包装了大部分典型的 iOS 开发人员都熟悉的标准 iOS UIKit UINavgationController 的视图堆栈管理 API。<NavigatorIOS> 提供了各种 API 来推送、弹出和操作一个视图堆栈。它还通过标题栏上可选的可除模按钮提供了前进和后退导航。<NavigationIOS> 组件是应用程序的根组件,如清单 3 所示。

清单 3. 创建 <NavigationIOS> 组件
var dwViewerApp = React.createClass({...render: function() {  return (    <NavigatorIOS ref='nav' style={styles.container}      initialRoute={{        component: ArticlesView,        title: 'Articles',        rightButtonTitle: 'Videos',        onRightButtonPress: this.onButPress,      }}     />    );  }});

initialRoute 特性指定要显示的初始视图,在本例中为 ArticlesView。路由包括要在视图中显示的标题,以及可选的按钮标题和触摸处理函数。如果要指定初始视图,标题栏的左侧和右侧会显示这些按钮。<NavigationIOS> 将一个 navigator 特性传递给它的所有直系子对象,在本例中为 ArticlesView。子对象可使用这个 navigator 特性来操作托管的视图堆栈。

使用 <ListView> 组件

文章列表由 ArticlesView 组件显示,该组件合成了一个 React Native <ListView>,如清单 4 所示。

清单 4. 合成一个 <ListView>
var ArticlesView = React.createClass({...render: function() {    ...    return (      <ListView        dataSource={this.state.dataSource}        renderRow={this.renderArticle}        style={styles.listView}      />    );},

尽管 <ListView> 没有包装原生的 UIKit UITableView 组件(几乎所有原生 iOS 应用程序都使用它来显示列表),但它提供了可在异步桥接操作上保持足够的性能的自己的版本。

<ListView> 通过 datasource 特性加载它的数据,该特性在这里被指定为 ArticleView 的 dataSource 状态变量。renderRow 特性设置为您之前看到的 renderArticle() 方法,该方法渲染了一个文章单元。

dataSource 状态变量通过 datasource.js 加载 <ListView> 的数据,该文件将该数据定义为一个静态编码的 JSON 对象数组。在首次显示视图中,会通过 ArticlesView 的 componentDidMount 处理函数抓取 <ListView> 的数据一次。

var DataSource = require('./datasource');...componentDidMount: function() {  this.setState({   dataSource:    this.state.dataSource.cloneWithRows(DataSource.getArticles()),   loaded: true,  });  },

在文章和视频之间导航

用户触摸右上角的 Videos 按钮时,将调用 ArticleView 的 onButPress() 方法。此方法将会调用 <NavigatorIOS> 的 push() 方法,将一个 VideosView 实例推送到堆栈上,导致视频列表从右侧滑入:

onButPress: function() {    this.refs.nav.push({      component: VideosView,      title: "Videos",  });  },

显示 VideosView 时,在标题栏上显示了一个 Articles 按钮(参见 图 4)。用户可以触摸该按钮,从堆栈中关闭当前视图并返回到文章列表。

放置 video-list 单元

video-list 单元通过将 React Native 组件组合在 VideosView 的 renderVideo 方法中来放置,如清单 5 所示。

清单 5. 放置一个 video-list 单元
renderVideo: function(video) {  return (    <TouchableOpacity      activeOpacity={0.5}      onPress={() => this.showVideo(video.title, video.url)}>      <View style={styles.videoscontainer}>        <Image source={{uri: video.icon}} style={styles.vicon} />        <View style={styles.videocellcontainer}>          <View style={styles.celltitlerow}>            <Text style={styles.title}>{video.title}</Text>            <Text style={styles.year}>({video.year})</Text>          </View>          <Text style={styles.description}>{video.desc}</Text>         </View>       </View>       </TouchableOpacity>    );  },

此布局看起来与文章单元的布局很相似。仅增加了一个 <Image> 组件,用于显示视频的图标。为了能够离线访问,这些静态的 PGN 文件必须通过应用程序的 Images.xcassets 文件添加到应用程序的资源包中。请参阅 React Native 文档中的 使用 Images.xcassets 将静态资源添加到应用程序 说明(向下滚动以查看该节)。

集成一个社区贡献的 React Native 组件

VideosView 的 Listview 的加载和视频选择的处理等同于 ArticlesView,留作练习供您跟踪分析。一个主要的区别是实际视频的显示。

没有使用 <WebView> 来显示视频,该应用程序使用一个第三方 <Video> React Native 组件:react-native-video(由社区成员 Brent Vatne 创建)。如果您想要将此组件添加到自己的应用程序中,请确保按照 Vatne 的 详细说明(下滚以查看它们)将它安装到您的 Xcode 项目中。创建您自己的应用程序时,您可能希望探索 GitHub 上 越来越多 由社区贡献的 React Native 组件。

这个第三方 <Video> 组件由 VideoViewer 类包装,如清单 6 所示。

清单 6. 包装 <Video> 组件
var VideoViewer = React.createClass({  render: function ()  {    return(      <View style={styles.vidcontainer}>      <Video source={this.props.source}       rate={1.0}                          volume={1.0}                       muted={false}                       paused={false}                      resizeMode="stretch"                  style={styles.video}       />       </View>       );  },

这个 VideoViewer 在通过 VideosView 的 showVideo() 方法选择一个视图时推送到视图堆栈上:

showVideo: function(title, url) {    this.props.navigator.push({      title: title,      component: VideoViewer,      passProps: {source: {uri: url}},    });  },

该应用程序的代码分析到此已完成了。

强大的工具,即时满足您的需求

非凡的调试支持

您不仅能通过 WebSocket 借助 Chrome 进行远程调试。当您的程序在执行期间崩溃时,设备屏幕上的一个 ListView 的一系列红色单元中还会显示堆栈轨迹。触摸任何单元,都会导致被引用的源文件在开发人员 PC 上由开发人员选择的编辑器中打开(这得益于连接的打包服务器,通过 REACT_EDITOR 变量进行设置),光标位于准确的错误代码行上!

单单作为一个开源库,React Native 也是一大进步。但让它大放异彩的是 React Native 随带的实用的工具集。这些工具利用了可供 JavaScript 开发人员使用的现有的丰富且成熟的工具。

图 7 显示了应用程序内的开发人员菜单,它在您运行 React Native 应用程序时通过一个热键弹出 — 无论是在模拟器中运行还是在实际设备上运行。您可以重新加载该应用程序,开始剖析代码,度量当前的每秒渲染帧数 (FPS)。您还可以通过 Chrome 或 Safari 内置的 JavaScript 调试器来远程调试您的 JavaScript 代码。借助远程调试,您可以单步调试,检查或修改时间点变量值,设置断点,等等。

图 7. 显示了应用程序内的开发人员菜单的原生应用程序

借助 Inspect Element 选项,您可以在原生 iOS 应用程序运行期间检查 React Native 组件的样式和属性。该显示视图在设备屏幕上弹出,类似于我们已熟悉的基于浏览器的检查元素布局。图 8 显示了这种应用程序内的覆盖图。

图 8. 支持类似浏览器的动态元素检查的应用程序内的覆盖图

这些应用程序内、屏幕上的开发人员辅助特性,是使用 pragmatic 的原生 iOS 开发人员梦寐以求但从未体验过的。使用 React Native 的 JavaScript 开发人员还可以在官方的 1.0 版发布之前使用它们。

结束语

如果您是梦想为应用商店编写 iOS 应用程序的 JavaScript 开发人员,那么您的梦想现在可以实现了。React Native 现在将您的 React 编程技能扩展到了 iOS,而且很快就会将它们扩展到 Android。丰富的社区支持可确保可供使用的新组件和特性 API 会无止境地出现。React Native 已展现出一种永不停歇的发展态势,我敢肯定,这将使它成为首选的主流 iOS 开发平台。React Native 使 iOS 移动应用程序开发变得比以往更加有趣。


下载

描述名字大小本文的示例应用程序的源代码mo-react-native-ios8.zip142KB


1 0