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, }, });
到此爲止,就是對當前移動開發的一些總體理解,有了知識地圖,下一步就開始步步前進!
爲何要搞這個東西?由於任何算法和技術都須要一個平臺來展現。