Ref: React Native跨平台移动应用开发html
后记:这本书博客味有点浓。前端
本篇涉及新建工程的若干套路,以及一点语法知识。java
(1)node
解决的一大核心问题:react
(2)linux
使用Javascript的严格模式。android
(3)ios
开发环境配置:程序员
https://gist.github.com/platonish/f913e8a691ae811524f47bfb7710437b
亲测,可用,开始建立工程:
unsw@unsw-UX303UB$ npm install -g react-native-cli /usr/local/node-v8.9.4-linux-x64/bin/react-native -> /usr/local/node-v8.9.4-linux-x64/lib/node_modules/react-native-cli/index.js + react-native-cli@2.0.1 updated 1 package in 1.176s unsw@unsw-UX303UB$ ls -a . ..
unsw@unsw-UX303UB$ react-native init HelloWorld This will walk you through creating a new React Native project in /root/android-workplace/HelloWorld Installing react-native... Consider installing yarn to make this faster: https://yarnpkg.com npm WARN deprecated connect@2.30.2: connect 2.x series is deprecated npm WARN deprecated gulp-util@3.0.8: gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5 npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN react-native@0.52.2 requires a peer of react@16.2.0 but none is installed. You must install peer dependencies yourself. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) + react-native@0.52.2 added 583 packages in 37.805s Setting up new React Native app in /root/android-workplace/HelloWorld Installing React... npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) + react@16.2.0 added 1 package in 4.133s Installing Jest... npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) + babel-preset-react-native@4.0.0 + babel-jest@22.1.0 + react-test-renderer@16.2.0 + jest@22.1.4 added 212 packages and updated 1 package in 19.407s To run your app on iOS: cd /root/android-workplace/HelloWorld react-native run-ios - or - Open ios/HelloWorld.xcodeproj in Xcode Hit the Run button To run your app on Android: cd /root/android-workplace/HelloWorld Have an Android emulator running (quickest way to get started), or a device connected react-native run-android
unsw@unsw-UX303UB$ cd HelloWorld/ unsw@unsw-UX303UB$ react-native start Scanning folders for symlinks in /root/android-workplace/HelloWorld/node_modules (19ms) ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ Running Metro Bundler on port 8081. │ │ │ │ Keep Metro running while developing on any JS projects. Feel free to │ │ close this tab and run your own Metro instance if you prefer. │ │ │ │ https://github.com/facebook/react-native │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ Looking for JS files in /root/android-workplace/HelloWorld Metro Bundler ready. Loading dependency graph, done.
You can run the packager on another port. $ react-native start --port=8088 Alternatively, find out what is using which ports on Windows with netstat. $ netstat -a -b -o Netstat gives you a PID, which you can use to kill the process. $ taskkill /pid 1234
有多是这两种状况致使的。 第一种,是没有注册、或者注册语句写错。正确的写法以下,引号中的AwesomeProject必定是这个项目的名称。 AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject); 第二种,多是8081端口被占用。那么如何测试这个错误呢? 步骤以下: 在项目文件夹中打开终端,输入react-native start 若是在结果中出现了Packager can't listen on port 8081,那么就证明了8081端口被占用了。 接下去要作的是再中断输入命令: lsof -n -i4TCP:8081,目的是列出被占用的端口列表 输入命令kill -9 <PID>,目的是删除对应PID的占用。这里的<PID>在第三步的端口列表中能够找到。 输入命令react-native run-ios从新启动项目便可。(我本身使用的是ios,若是是andriod,那么直接替换ios成andriod就能够了) 果真,删除后从新运行程序就没有这样的报错了,一切正常啦!太好了!
Android Studio模拟器可能提早占用8081,建议留给RN。
lsof -i :8081 列出8081谁在用,而后杀掉,腾出地方。 kill -9 <PID>
与服务器连接完成后,加载代码,运行成功!
unsw@unsw-UX303UB$ react-native run-android
问题来了,js code在哪里? Developing mobile apps with React Native in WebStorm!
以后便成了完全的网页开发!
解决这个问题须要借助两个工具:
1. create-react-native-app(下文简称CRNA);
2. Expo(原名Exponent)。
好处:
使用 CRNA 建立 RN 应用只是不用安装 iOS 和 Android 的编译环境了,可是 node 仍是必须的,而后经过下面的 node 命令安装 CRNA 这个工具。
它只包含了 JS 部分的代码。
经过 npm start
启动该应用后,会生成一个二维码。
$ npm install -g create-react-native-app
$ npm start
可见,摆脱了react-native命令,也便是减小了对原生代码的依赖。
Step 1:
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,其使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
Node.js 的包管理器 npm,是全球最大的开源库生态系统,功能及其强大。
首先,在Ubuntu上安装NPM(Node Package Manger) (avaliable)
Step 2:
安装watchman: https://facebook.github.io/watchman/docs/install.html#installing-from-source
$ git clone https://github.com/facebook/watchman.git
$ cd watchman
$ git checkout v4.9.0 # the latest stable release
$ ./autogen.sh # --> install libtool firstly, as following.
$ ./configure
$ make
$ sudo make install
间接安装,brew相似于apt-get,能够管理软件的安装和卸载。
Ubuntu 安装brew【很差,貌似还须要先安装ruby?烦】
直接安装更好:https://askubuntu.com/questions/625523/libtool-installed-but-not-on-path-after-installation
sudo apt-get install libtool
Step 3:
Ref: React Native开源项目如何运行(附一波开源项目)
git clone https://github.com/poberwong/react-native-gank.git cd react-native-gank/ npm install <-- react-native前必须执行的一个鬼东西
扩展:
开源项目为了减小空间,并无提交node_mudules目录,须要咱们本身安装。
unsw@unsw-UX303UB$ du -h --max-depth=1
108K ./ios
51M ./android
244M ./node_modules
76K ./jscore
7.8M ./.git
303M .
node_modules 是整个项目的依赖, 里面包含什么呢?
包含的文件所有都写在package.json
文件中了。 这个文件是必不可少的。咱们须要按照这个列表下载。
React native项目是经过nodejs构建的,因此在nodejs项目中都须要package.json
文件。
具体你们能够看看nodejs相关知识 ,七天学会 Nodejs。
Goto: [NodeJS] Basic knowledge about NodeJS due to React Native
开源项目汇总 https://github.com/liuhongjun719/react-native-DaidaiHelperNew 借贷助手 https://github.com/liuhongjun719/react-native-BabyHealth- 仿宝宝健康 https://github.com/nihgwu/react-native-sudoku 数独 https://github.com/attentiveness/reading reading https://github.com/CoderGLM/ReactNativeLeaning https://github.com/eesc88/programmer 云翻译客户端 https://github.com/jiangqqlmj/GaGaMall 嘎嘎商城 https://github.com/879479119/Bilibili-React-Native 仿B站客户端 https://github.com/Shuijwan/marvel漫威电影客户端 https://github.com/talentjiang/react_native_office公司移动OA办公客户端 https://github.com/yohnz/maoyanFilm仿猫眼电影客户端 https://github.com/soliury/noder-react-nativeCNode论坛客户端 https://github.com/Kennytian/LagouApp仿拉勾网客户端 https://github.com/SFantasy/WeiboReactNativeiOS新浪微博客户端 https://github.com/kailuo99/toutiaoiOS资讯头条APP https://github.com/xiekw2010/react-native-gitfeedGithub客户端 https://github.com/iSimar/HackerNews-React-NativeHacker新闻客户端 https://github.com/starzhy/TheOneCoder码农客户端 https://github.com/tabalt/ReactNativeNews新闻客户端 https://github.com/vczero/React-Dou豆瓣搜索客户端 https://github.com/race604/ZhiHuDaily-React-Native知乎日报客户端 做者:于连林520wcf 连接:https://www.jianshu.com/p/240d5ab43a48 來源:简书 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
1. 启动虚拟机。
2. 启动服务:
unsw@unsw-UX303UB$ react-native start
3. 加载至虚拟机并运行。
unsw@unsw-UX303UB$ react-native run-android
(node:4467) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. Starting JS server... Building and installing the app on the device (cd android && ./gradlew installDebug... :app:preBuild UP-TO-DATE :app:preDebugBuild UP-TO-DATE :app:checkDebugManifest :app:preReleaseBuild UP-TO-DATE :app:prepareComAndroidSupportAppcompatV72301Library UP-TO-DATE :app:prepareComAndroidSupportRecyclerviewV72301Library UP-TO-DATE :app:prepareComAndroidSupportSupportV42301Library UP-TO-DATE :app:prepareComFacebookFrescoDrawee081Library UP-TO-DATE :app:prepareComFacebookFrescoFbcore081Library UP-TO-DATE :app:prepareComFacebookFrescoFresco081Library UP-TO-DATE :app:prepareComFacebookFrescoImagepipeline081Library UP-TO-DATE :app:prepareComFacebookFrescoImagepipelineOkhttp081Library UP-TO-DATE :app:prepareComFacebookReactReactNative0251Library UP-TO-DATE :app:prepareOrgWebkitAndroidJscR174650Library UP-TO-DATE :app:prepareDebugDependencies :app:compileDebugAidl UP-TO-DATE :app:compileDebugRenderscript UP-TO-DATE :app:generateDebugBuildConfig UP-TO-DATE :app:generateDebugAssets UP-TO-DATE :app:mergeDebugAssets UP-TO-DATE :app:generateDebugResValues UP-TO-DATE :app:generateDebugResources UP-TO-DATE :app:mergeDebugResources UP-TO-DATE :app:bundleDebugJsAndAssets SKIPPED :app:processDebugManifest UP-TO-DATE :app:processDebugResources UP-TO-DATE :app:generateDebugSources UP-TO-DATE :app:processDebugJavaRes UP-TO-DATE :app:compileDebugJavaWithJavac UP-TO-DATE :app:compileDebugNdk UP-TO-DATE :app:compileDebugSources UP-TO-DATE :app:preDexDebug UP-TO-DATE :app:dexDebug UP-TO-DATE :app:validateDebugSigning :app:packageDebug UP-TO-DATE :app:zipalignDebug UP-TO-DATE :app:assembleDebug UP-TO-DATE :app:installDebug Installing APK 'app-debug.apk' on 'Pixel_2_-_API_26(AVD) - 8.0.0' Installed on 1 device. BUILD SUCCESSFUL Total time: 10.866 secs This build could be faster, please consider using the Gradle Daemon: http://gradle.org/docs/2.4/userguide/gradle_daemon.html Starting the app on emulator-5554 (/home/unsw/Android/Sdk/platform-tools/adb -s emulator-5554 shell am start -n com.reactnativegank/.MainActivity)... Starting: Intent { cmp=com.reactnativegank/.MainActivity }
如此,咱们经过上手demo 相关代码在这里,从而了解【props】和【state】 这些个概念。
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { mavenLocal() jcenter() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url "$rootDir/../node_modules/react-native/android" } } }
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
(暂时跟着这篇学习方针走!挽救IT生涯!)
WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。
步骤:
添加软件源 sudo add-apt-repository ppa:openjdk-r/ppa
更新源 sudo apt-get update
安装 openjdk-8-jdk sudo apt-get install openjdk-8-jdk
而后就能够切换版本:
unsw@unsw-UX303UB$ sudo update-alternatives --config java There are 2 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1071 auto mode 1 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1071 manual mode 2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1069 manual mode Press enter to keep the current choice[*], or type selection number: 2 update-alternatives: using /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java to provide /usr/bin/java (java) in manual mode
如此,pycharm,webstorm恢复使用,激活:http://blog.csdn.net/voke_/article/details/76418116
还有记得打开755权限至少。
接下来,安装一些插件,以及进行一些经常使用配置。好比RN组件库的安装,添加一些经常使用的Live Templates等。
Ref: Developing mobile apps with React Native in WebStorm
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
经过实例学习:
http://static.vgee.cn/static/index.html
http://www.ruanyifeng.com/blog/2015/07/flex-examples.html
布局工具:codepen
https://codepen.io/LandonSchropp/pen/KpzzGo
如今的 App 大多都比较简单,无非就是布局的展现,网络数据的获取等等。
这里要说明的是,若是你是 Android 或 iOS 工程师,那你须要习惯一下 RN 处理 Json 数据的方式(或者说 Web 处理 Json 的方式),
咱们经过网络请求回来的 Json Object 数据就能够直接进行操做,而不像 Native 开发,还须要经过什么额外的工具去进行 Json 的转换。这也是 Web 开发比较方便的地方。
不管 Json Object 转 Json 字符串,仍是 Json 字符串转 Json Object,都是很是方便的。
若是非要把网络数据进行本地存储,那也很方便,经过解构赋值,直接就能够赋值给你建立的 Model 了。
JSON 与 JS 对象的关系
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可使用引号包裹的 var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
JSON 和 JS 对象互转
要实现从对象转换为 JSON 字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
要实现从 JSON 转换为对象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}
XMLHttpRequest 对象提供了对 HTTP 协议的彻底的访问,包括作出 POST 和 HEAD 请求以及普通的 GET 请求的能力。
$.ajax
迁移到 Fetch
jQuery 是一个“写的更少,但作的更多”的轻量级 JavaScript 库。【将要过期的东西】
XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式很是混乱,并且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。Fetch 的出现就是为了解决 XHR 的问题。
var xhr = new XMLHttpRequest();
xhr.open('GET', url); xhr.responseType = 'json'; xhr.onload = function() { console.log(xhr.response); }; xhr.onerror = function() { console.log("Oops, error"); }; xhr.send();
使用 Fetch 后,顿时看起来好一点:
fetch(url).then(function(response) { return response.json();
}).then(function(data) { console.log(data);
}).catch(function(e) { console.log("Oops, error");
});
使用 ES6 的 箭头函数 后:
fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))
最终优化:
是有 Callback 的影子,而后让咱们写异步代码就像写同步代码同样爽;但,这是还未流行的最新的ES7方法。
try { let response = await fetch(url); let data = response.json(); console.log(data); } catch(e) { console.log("Oops, error", e); } // 注:这段代码若是想运行,外面须要包一个 async function
有必要先学习一下 Promise,推荐阅读 MDN Promise 教程。旧浏览器不支持 Promise,须要使用 polyfill es6-promise 。
Promise 对象用于表示一个异步操做的最终状态(完成或失败),以及其返回的值。
这是流行的方法:ES6 的 Promise 对象,以及 test online【在线测试js代码的地方】。
一个任务时
function helloWorld (ready) { return new Promise(function (resolve, reject) { if (ready) { resolve("Hello World!"); } else { reject("Good bye!"); } }); } helloWorld(true).then(function (message) { alert(message); }, function (error) { alert(error); });
在 Promise 对象当中有两个重要方法————resolve
和 reject
。
resolve
方法可使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操做,在这个例子当中就是 Hello World!字符串。
reject
方法则是将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操做。
共三种状态:
Fulfilled 能够理解为成功的状态
Rejected 能够理解为失败的状态
Pending 既不是 Fulfilld 也不是 Rejected 的状态,能够理解为 Promise 对象实例建立时候的初始状态
多个任务时
unction printHello (ready) { return new Promise(function (resolve, reject) { if (ready) { resolve("Hello"); } else { reject("Good bye!"); } }); } function printWorld () { alert("World"); } function printExclamation () { alert("!"); } printHello(true) .then(function(message){ // tast 1 alert(message); }) .then(printWorld) // tast 2 .then(printExclamation); // tast 3
In addition,
catch
方法是 then(onFulfilled, onRejected)
方法当中 onRejected
函数的一个简单的写法,也就是说能够写成 then(fn).catch(fn)
,至关于 then(fn).then(null, fn)
。使用 catch
的写法比通常的写法更加清晰明确。
Promise.all
能够接收一个元素为 Promise 对象的数组做为参数,当这个数组里面全部的 Promise 对象都变为 resolve 时,该方法才会返回。
var p1 = new Promise(function (resolve) { setTimeout(function () { resolve("Hello"); }, 3000); }); var p2 = new Promise(function (resolve) { setTimeout(function () { resolve("World"); }, 1000); }); Promise.all([p1, p2]).then(function (result) { console.log(result); // ["Hello", "World"] });
In addition,
Promise.race
,它一样接收一个数组,不一样的是只要该数组中的 Promise 对象的状态发生变化(不管是 resolve 仍是 reject)该方法都会返回。
网络请求结束后,确定是少不了数据的展现和更新。
这时又会涉及到一个很重要的知识点,就是【props】和【state】,RN中全部数据的传递和控制,都离不开这两个部分。
因此,请务必在发起网络请求前就要搞懂这两个内容。
Goto: [RN] React Native Practice 50 lectures
From: React Native by Example
可见,就是写js文件罢了,那么JS的学习就成了接下来的重点 --> ECMAScript 6 入门
对于一个程序员来讲,语言的学习不是个事儿!
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View } 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', }); export default class App extends Component<{}> { 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> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });
到此为止,就是对当前移动开发的一些总体理解,有了知识地图,下一步就开始步步前进!
为何要搞这个东西?由于任何算法和技术都须要一个平台来展现。