前言
“一次構建,多處運行”,跨平臺APP帶著這股風潮把火燒到了前端,為開發(fā)者帶來無盡的遐想。現(xiàn)有的流行跨平臺框架有以下:
1. ?基于單WebView的開發(fā)框架。開發(fā)者可以使用現(xiàn)有的最新web技術,開發(fā)出單頁面web應用。同時利用JSBridge,又能獲取原生的API,從而使web應用具有了原生應用的功能。Cordova+IONIC可以說是這個潮流的代表,也是跨平臺APP的先鋒。然而這類跨平臺應用的缺點是不流暢,在安卓手機上體驗較差。
2. Hybrid方向。也就是原生應用配合HTML5技術,讓APP具有了部分跨平臺的功能。Hybrid也是現(xiàn)在各大互聯(lián)網(wǎng)企業(yè)采用較多的跨平臺開發(fā)方式。這類APP在體驗上優(yōu)于單WebView的APP,并且能夠極大提高開發(fā)效率。然而這種方式離“一次構建,多處運行”的設想還是有很大距離,畢竟依然需要針對不同的移動平臺進行原生開發(fā)。
3. 使用Javascript開發(fā)純原生應用。
和ReactNative相比,Nativescript最大的特點是可以獲得100%的原生API。也就是說,開發(fā)者可以通過Javascript獲取和原生開發(fā)語言同樣多的原生接口。下面,我們通過實現(xiàn)一個簡單的計算器,來體會一下Nativescript的開發(fā)思想。同時,我們能體會到“獲取所有原生API”帶來的巨大好處。
你可以先在這里看到最終的結果。
注意輸入的數(shù)字的字體會隨著文本長度逐漸變小,想想這個功能怎么實現(xiàn)。

準備
首先需要搭建開發(fā)環(huán)境,請參考官方的文檔。你可以使用下面的命令來檢測Nativescript是否安轉完成:
tns doctor
Nativescript支持純Javascript,同時也支持Angular2。我們選擇Angular2和Typescript進行開發(fā),體會一下Angular2帶來的開發(fā)便利。
創(chuàng)建我們的項目
tns create NSCalculator --ng
這個命令會在當前目錄下新建NSCalculator文件夾,同時安裝好所需的第三方依賴。其實這個命令還給你新建一個Demo,運行下面的命令,你就會看到你的第一個Nativescript應用
tns platform add ios
tns run ios --emulator
拆分
使用Visual Studio Code打開文件,有如下的文件夾結構

我們的代碼將會組織在app目錄下,所以只需考慮這個文件夾。
main.ts是整個應用的啟動文件,我們現(xiàn)在不需要更改它。我們看到main.ts里面引入了app.component模塊,app.component將會被改造成我們的計算器組件。
在改造app.component.ts前,我們先考慮一下如何將計算器拆分成一個個組件。

首先從功能上對計算器進行拆分。計算器由Displayer和Keyboard兩個部分,Keyboard由Button組成?;诖耍覀冊赼pp目錄下新增三個文件夾:Displayer,Keyboard,NSButton。
布局
組件化開發(fā)有兩種常用方式,一種是由大到小開發(fā),也就是Calculator -> Displayer -> Keyboard -> Button,一種是由小到大開發(fā),也就是 Button -> Keyboard -> Displayer -> Calculator。當然你也可以混合開發(fā)。本例采用由大到小的開發(fā)方式。
刪除app.component.ts里面的內容,用以下代替:
```
dd
```
運行以下命令,你就能看到效果
tns livesync ios --emulator --watch?
和 tns run ios 命令不同,這個命令會監(jiān)視你的文件變化并自動構建部署新的應用。

Nativescript的布局方式和安卓原生的布局方式非常類似。對于計算器,我們的Displayer需要一個固定的高度,Keyboard需要占據(jù)全部剩余的空間。因此,Calculator的第一級布局使用了GridLayout。rows="auto,*" 表示Gridlayout為兩行,第一行高度由內容(auto)決定,第二行高度占據(jù)全部剩余空間(*)。columns="*"表示Gridlayout分為一列布局,這一列的寬度占據(jù)全部空間。
我們?yōu)镈isplayer選擇了StackLayout布局,這是因為我們需要把Label靠右下角對齊。我們?yōu)镵eyboard選擇了GridLayout布局,這很好理解,因為我們需要一個5x4的格子用來放置計算器的按鈕。
組件
目前為止我們的APP只有一個組件AppComponent,這非常不利于項目的擴展。幸運的是Nativescript支持Angular2.0的全部功能,我們可以使用Angular來實現(xiàn)Displayer和Keyboard組件。
在app目錄下新建Keyboard文件夾,在Keyboard文件里新增keyboard.component.ts,keyboard.html,以及keyboard.css文件。內容如下:
應用界面并沒有任何變化,我們還需要在app.component.ts中引入Keyboard組件。修改后的文件如下
現(xiàn)在我們的計算器有點樣子了:

Keyboard組件
但是現(xiàn)在的Keyboard還不能提供任何功能,Keyboard不能響應點擊事件,也不能把數(shù)據(jù)傳遞給Displayer。接下來我們就要為Keyboard加上這些功能。
交互
要監(jiān)聽Keyboard的點擊事件,最直觀的答案就是為每個按鈕設置touch事件監(jiān)聽器,在這個計算器應用中我們需要設置19次!而且我們的監(jiān)聽邏輯不能復用,雖然他們的功能很相似!這是不可接受的。所以,我們應該把按鈕也做成一個Angular組件,因為組件是可以復用的。
那么這個按鈕組件需要哪些功能呢??當點擊按鈕時,按鈕的背景色需要改變,并且需要把這個點擊事件告知其他組件。
在app目錄下新建NSButton文件夾,同時在NSButton文件夾里新增一下文件: nsbutton.component.ts, nsbutton.css。
然后,需要在Keyboard組件里引入NSButton。修改keyboard.component.ts和keyboard.html文件如下:
現(xiàn)在,我們的按鈕組件就有了一個漂亮的點擊動畫。

不過Keyboard的點擊事件還不能通知給Displayer,我們接著來增加這個功能,修改nsbuttom.component.ts, keyboard.component.ts, app.component.ts如下:
這樣我們的Keyboard點擊就能實時顯示在Disapler上面了。

原生API
對比我們的計算器和ios原生計算器,我們發(fā)現(xiàn)原生計算器的Displayer會自動調整字體大小,以保證顯示的數(shù)字完全展示。得益于Nativescript,我們也能通過Javascript調用這套API,實現(xiàn)相同的效果。修改app.comonent.ts如下:
總結
得益于Nativescript可以訪問100%的原生API, 我們不需要寫任何原生代碼,就能獲得和原生代碼一樣的能力。這可以說是Nativescript相比于其他平臺,比如React Native, 最大的優(yōu)勢。在現(xiàn)階段,Nativescript應該是最成熟的,性能最好的跨平臺APP構建方案。