最近小小嘗試了下 ReactNative + TypeScript 開發APP,爬了無數坑之后總算弄出來個結果,重要的地方記錄下,后面會附上示例代碼:
1、開發工具的選擇
windows 平台我接觸的開發工具主要三個,
WebStorm,Intellij IDEA 2016.2 版本,https://www.jetbrains.com/
這兩個我都試過,開發完全沒問題的,還有PHPStorm估計也行吧,沒試過。
另外還有一個是VisualStudioCode:https://code.visualstudio.com/b?utm_expid=101350005-27.GqBWbOBuSRqlazQC_nNSRg.1
對與 iOS 平台應該是不用選的就是 Nuclide 了吧,我是沒用過哈,不知道怎么用,不過用過 Atom 感覺還是很酷的。
平時習慣用 jetbrains 的 IDE ,每個都絕對神器,VisualCode 感覺實在太難用了,堅持了一段時間還是放棄了。
下面示例都是用的 Intellij IDEA 2016.2
預覽下:
經過一番配置后,import 等導入和代碼提示等等都是沒問題的
2、基礎開發環境安裝
這個我就不說了,直接看這個網站就行了上面已經寫得很完善了 http://reactnative.cn/ ,照着文檔安裝配置應該沒什么問題的,文檔看不懂的話網站的站長博客里面還有全套的視頻講解非常詳細了,地址:http://reactnative.cn/post/759。
3、安裝 TypeScript 開發環境
# 先 cd 到你的項目目錄,如 myproject 目錄下再執行下面命令 npm install -g typescript npm install typescript tsc --init # 未安裝 tsd 則先安裝再進行項目初始化 npm install -g tsd tsd init && tsd install react-native --save
tsd 初始化安裝后,會生成 tsconfig.json 文件,貌似 react-native 初始化新項目的時候就有這么個文件來着,忘了,如果tsd初始化之前已存在該文件可直接刪除。
查看 tsconfig.json 文件
{ "compilerOptions": { "target": "es6", "allowJs": true, "jsx": "react", //"outDir": "artifacts", //"rootDir": "src", "sourceMap": false, "noImplicitAny": false }, "filesGlob": [ "typings/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx" ], "exclude": [ "node_modules" ] }
個人建議是 outDir 參數建議不要設置,使用默認值就行,這樣每次修改 .ts 文件后就會直接在當前目錄下生成同名的 es6語法編譯后 .js 文件,當 index.android.js 入口文件加載項目文件時則很方便,如下圖:
以上配置完成就可以開始使用 TypeScript 開發了。
簡單做了個 List 加載文章列表的功能,實現起來很簡單方便,和原生Android開發比起來簡直快了太多太多。
不過一開始遇到了很多坑,主要還是由於對 TypeScript 不太熟悉
如 style 的設置,總是提示類型錯誤:
Error:(20, 15) TS2322:Type '{ flex: number; flexDirection: string; }' is not assignable to type 'ViewStyle'. Types of property 'flexDirection' are incompatible. Type 'string' is not assignable to type '"row" | "column" | "row-reverse" | "column-reverse"'. Type 'string' is not assignable to type '"column-reverse"'.
類似上面這種錯誤,很是莫名其妙,搞了好半天才明白原來樣式參數配置是需要進行類型轉換,這也是 TypeScript很特色的地方啦
如下面這樣:
4、TypeScript 跟 ReactNative 開發的關系
最后說一下這兩者是如何發生關系的,可能還有跟我一樣的小白還沒弄清楚,我就按照自己的理解來說啦,
你用 TypeScript 語法寫的 .ts .tsx 等后綴的程序是不能直接運行的,而是會被 tsconfig.json 配置中的 “target”: “es6”, 這項配置轉換為 es6 語法的 .js 文件。
TypeScript 中的 import 只會加載 .ts .tsx 后綴的文件,而 Javascript 中的 import 只能加載 .js 等后綴的文件,
所以,當 ReactNative 啟動時,首先加載入口文件,如 index.android.js ,代碼如下:
import { AppRegistry } from 'react-native'; import IndexNavigator from './application/src/controller/navigator/IndexNavigator'; AppRegistry.registerComponent('mogudan', () => IndexNavigator);
其中 import IndexNavigator from … 這一行加載的不是 IndexNavigator.ts 而是編譯后生成的 IndexNavigator.js 文件,下面對比兩個文件的差異:
IndexNavigator.ts
/** * Created by ZHOUZ on 2016-08-26. */ import * as React from 'react'; import {Navigator} from 'react-native'; import IndexPage from '../page/IndexPage' export default class IndexNavigator extends React.Component<any, any> { render() { let defaultName = 'IndexPage3311113'; let defaultComponent = IndexPage; return ( <Navigator initialRoute={{ name: defaultName, component: defaultComponent }} configureScene={(route) => Navigator.SceneConfigs.VerticalDownSwipeJump } renderScene={(route: any, navigator) => { let Component = route.component; return <Component {...route.params} navigator={navigator} /> }} /> ); } }
IndexNavigator.js
為自動編譯后生成的es6語法的 javascript 代碼
"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; /** * Created by ZHOUZ on 2016-08-26. */ const React = require('react'); const react_native_1 = require('react-native'); const IndexPage_1 = require('../page/IndexPage'); class IndexNavigator extends React.Component { render() { let defaultName = 'IndexPage3311113'; let defaultComponent = IndexPage_1.default; return (React.createElement(react_native_1.Navigator, {initialRoute: { name: defaultName, component: defaultComponent }, configureScene: (route) => react_native_1.Navigator.SceneConfigs.VerticalDownSwipeJump, renderScene: (route, navigator) => { let Component = route.component; return React.createElement(Component, __assign({}, route.params, {navigator: navigator})); }})); } } Object.defineProperty(exports, "__esModule", { value: true }); exports.default = IndexNavigator;
大概就是這樣了,最最后放上我做的示例代碼,只包含 application 目錄下的文件,android,ios 目錄都是 react-native 自動生成的大家都一樣的。
文件下載地址: http://download.csdn.net/detail/zsjangel/9618350
補充一個問題,開發時使用 fetch 會遇到提示找不到的解決辦法,
http://blog.csdn.net/zhouzme/article/details/52390197