前 mPaaS H5 容器 Demo 源碼已發(fā)布至 GitHub,全新的接入方式讓你可以一鍵集成 mPaaS 環(huán)境并快速接入 H5 容器,體驗統(tǒng)一的容器和內(nèi)核,獲取媲美原生的 Hybrid 方案及完美的動態(tài)能力。
目前支付寶有 2 套 Hybrid 方案: HTML5 容器與小程序。小程序是最近幾年才出來,H5 容器已經(jīng)有了很長時間的歷史,所以我們就先從 H5 容器說起。
在支付寶中,HTML5 容器架構(gòu)如圖所示:
最上層是瀏覽器,這塊就是大家常見的 Web 開發(fā)環(huán)境,包括 HTML、CSS、JavaScript等。H5 容器作為中間層,將瀏覽器和支付寶底層框架有機結(jié)合起來,在 H5 容器里面有 2 個非常重要的概念: JSBridge 和 離線包,后面會做詳細介紹。支付寶底層框架會給 H5 容器提供 Native 的能力,這其中就包括 RPC(遠程過程調(diào)用,用來實現(xiàn) APP 和服務(wù)器通信)、支付、掃一掃等。
JSBridge 是 H5 容器的基石,橋接了 JS 環(huán)境與 Native,實現(xiàn)了 Native 代碼和 瀏覽器 環(huán)境的雙向通信,Native 代碼可以通過調(diào)用 瀏覽器 提供的接口運行JS,從而實現(xiàn)調(diào)用 JS 函數(shù)、傳遞參數(shù)到 JS 環(huán)境等;而瀏覽器到JS環(huán)境的通信是通過 Native 攔截瀏覽器的請求來實現(xiàn),請求可以是網(wǎng)絡(luò)請求或者是一些內(nèi)部函數(shù)的調(diào)用。
那么 JSBridge 會帶來什么好處呢,在傳統(tǒng)的 Web 開發(fā)場景,H5 頁面會通過 HTTP 的 GET 或者 POST 請求到后臺獲取數(shù)據(jù),就會用到 jQuery 等 AJAX 框架。但是 H5 頁面中的 JS 函數(shù)公開的,沒法做一些加密邏輯,同時對于無法優(yōu)化網(wǎng)絡(luò)。這幾年隨著 4G 和流量卡的普及,讓手機網(wǎng)絡(luò)變得更快、更便宜,在這之前大量用戶會面臨流量不足、信號差、網(wǎng)絡(luò)不穩(wěn)定的情況,這些場景在現(xiàn)在依然存在,而純 Web 方案是沒法提供相關(guān)的優(yōu)化。
H5 容器提供的 JSBridge 解決了這個問題,所有 H5 頁面需要從后臺獲取的數(shù)據(jù)都通過 JS Bridge 調(diào)用 Native 的 RPC SDK 來獲取。這樣實際 App 請求的數(shù)據(jù)都是由 RPC SDK 來發(fā)送,從而可以實現(xiàn)安全加密、簽名校驗、弱網(wǎng)優(yōu)化、流量優(yōu)化的功能。Native 層的這些功能是 Web 頁面開發(fā)人員無感知的,所以業(yè)務(wù)開發(fā)人員只需要專注其自身的業(yè)務(wù)開發(fā)即可。安全性由支付寶底層 SDK 保障。
H5 容器提供了 2 種擴展方式:
1. JSAPI
JSAPI 方式給 H5 頁面增加了 Native 功能調(diào)用接口,通過實現(xiàn)自定義 JSAPI 類中的 handler 方式,可以以 Native 的形式實現(xiàn)特定功能,例如調(diào)用 Native 加密函數(shù)。
2. 事件
H5 容器在狀態(tài)變化時會發(fā)送事件,通過監(jiān)聽 H5 容器特定事件,可以實現(xiàn)對 H5 容器生命周期的處理,比如修改加載進度條顏色、修改頁面導航欄等。事件提供了更強的定制性,完全可以滿足對 H5 容器的各種自定義需求。
H5 容器離線包是 H5 容器用戶體驗的關(guān)鍵。
在 APP 里面打開一個線上頁面的時候,通常會有一個白屏的階段,這是瀏覽器需要從服務(wù)器下載 HTML 資源。由于手機網(wǎng)絡(luò)的限制,這個時間會很不確定,通常會花費 300ms 以上的時間,用戶在這個時間里面就會看到頁面白屏。
為了優(yōu)化 H5 容器用戶體驗,減少白屏時間,支付寶在 H5 容器中引入了離線包技術(shù)。離線包可以簡單理解為一個 zip 壓縮包,其中包含前端頁面所需的 HTML、CSS、JS、圖片等資源。內(nèi)置到客戶端后,H5 容器打開離線包頁面時會直接從離線包中獲取資源,這個是毫秒的訪問時間,消除了打開頁面白屏現(xiàn)象。
在支付寶中,離線包分為 2 種:普通的業(yè)務(wù)資源包和公共資源包。先說公共資源包吧,公共資源包中會包含一些框架 JS、CSS、常見圖片等,這些資源在整個 App 里面就只保存一份;而業(yè)務(wù)資源包中只保存該業(yè)務(wù)所需的頁面靜態(tài)資源,業(yè)務(wù)之間是相互獨立解耦的。這樣一個業(yè)務(wù)的頁面資源就會同時來自其業(yè)務(wù)資源包和公共資源包,公共資源包的存在優(yōu)化了 App 大小。
為了滿足快速發(fā)布的需求,H5 容器離線包提供了更新機制,以單個離線包作為更新維度。因為單個離線包業(yè)務(wù)很簡單,所以離線包的大小是可控的,通常小于 500KB,這樣單個離線包的更新時間可控,可以做到用戶無感知。在一些極端網(wǎng)絡(luò)場景下,新的業(yè)務(wù)資源包沒有更新超過,而我們又期望用戶使用的是最新的業(yè)務(wù),這個時候 fallback 訪問機制就會發(fā)揮作用。每個離線包資源都會在服務(wù)器存放一份,在剛剛說到的極端場景下,用戶會訪問服務(wù)器的 fallback 地址獲取資源,從而保障頁面可用。
結(jié)合前面說到的離線包后,整個 H5 容器渲染流程如下。其中離線包資源的更新、下載對用戶無感知,頁面訪問的資源是來自離線包還是來自 fallback 地址對前端是無感知的。
為了提高 H5 容器穩(wěn)定性,支付寶在安卓系統(tǒng)上使用了 UC Webview,UC Webview 的崩潰率和ANR率遠低于系統(tǒng)瀏覽器,而且徹底規(guī)避了安卓系統(tǒng) Webview 碎片化問題,相信做過安卓前端頁面兼容的同學一定可以體會到使用一個瀏覽器內(nèi)核的好處。
H5 容器作為一個成熟的 Hybrid 方案可以滿足大部分的業(yè)務(wù)場景需求,但是其依然存在一些局限性。H5 容器的業(yè)務(wù)開發(fā)部分還保持著前端開發(fā)思維,畢竟整個過程都是使用的前端技術(shù),只需要在業(yè)務(wù)開發(fā)完成后集成到 APP 中完成測試。但是客戶端開發(fā)其中還有很多關(guān)鍵的概念,例如 iOS 的 ViewController 、Android 的 Activity 等,對客戶端頁面棧有清楚的了解更有助于開發(fā) H5 容器。同時 H5 容器還存在一個致命的問題就是無法管控質(zhì)量,寬泛的前端規(guī)范讓管控變得異常困難。
為了解決 H5 容器的局限性,順應(yīng)當前 APP 共享開放的需求,支付寶推出了新的 Hybrid 方案:支付寶小程序。支付寶小程序一種全新的開放模式,它運行在支付寶客戶端,可以被便捷地獲取和傳播,為終端用戶提供更優(yōu)的用戶體驗 。支付寶小程序基于 Web 技術(shù),因此學習成本低;其一套代碼同時支持 iOS 和 Android;并提供了豐富組件和 API;完全為 APP 開發(fā)而生。目前支付寶小程序已經(jīng)提供 2000 多個開放接口,API 日調(diào)用次數(shù)超過 25 億次,擁有超過 100 萬的合作伙伴和超過 10 萬個活躍服務(wù)商。
支付寶小程序同時還支持了阿里系多個 App ,包括口碑、高德和釘釘。
那么支付寶小程序是怎么解決 H5 容器的局限性呢?首先支付寶小程序是基于一個定制的 DSL 語言,不是前端的標準,但是類似。在 DSL 規(guī)則下業(yè)務(wù)進行小程序的開發(fā),不支持直接操作 DOM,這種 DSL 規(guī)則下的自由可以有效的進行質(zhì)量管控。另外支付寶小程序可以提供比 H5 小程序更優(yōu)秀的性能、體驗和兼容性,可以無感替換底層框架,應(yīng)對遇到的性能問題。
目前支付寶小程序也支持前面提到的 H5 容器所使用的離線包技術(shù),同時也支持 JSAPI 和事件的擴展方式,提供了更大的靈活性。
支付寶小程序的 DSL 語言包括了 4 部分:
文件用來提供小程序相關(guān)的配置,這里就強調(diào)了 page 和 window 的概念,支持用戶去配置導航欄等 APP 開發(fā)中的概念。
可以理解為小孩程序的頁面 HTML,不支持直接操作 DOM 保障了頁面邏輯的可控。
用來描述代碼邏輯,提供了 Page 中所需的各種生命周期,讓開發(fā)者有APP 中的各種概念。
類似于 H5 中的 CSS,支持大部分 CSS 語法,讓前端開發(fā)可以快速完成小程序 UI 設(shè)計。
目前支付寶小程序已經(jīng)逐步開放給個人開發(fā)者使用,大家可以申請開通,享受支付寶帶來的流量。
支付寶沉淀的 Hybrid 方案 H5 容器和小程序已經(jīng)經(jīng)過實際嚴苛的業(yè)務(wù)考驗,通過前面的介紹相信大家已經(jīng)有了了解。
從 0 開始開發(fā)一套 Hybrid 框架需要大量的人力以及反復的業(yè)務(wù)驗證,對于大部分公司來說成本太高。
而使用開源的 Hybrid 框架,例如 Cordova、Weex、React Native、Flutter等會面臨一個非常致命的問題,就是遇到框架層的問題,很難獲得及時有效的技術(shù)支持。
目前支付寶的 Hybrid 方案已經(jīng)借助移動開發(fā)平臺 mPaaS 對外輸出,解決前面提到的痛點,讓你直接和支付寶使用同一套框架層代碼,而且提供及時的技術(shù)支持。
mPaaS 是一站式移動開發(fā)解決方案,提供了移動開發(fā)所需的 5 大組件:MGS、MDS、MPS、MAS、MSS,這些組件都是基于支付寶,經(jīng)過實際業(yè)務(wù)考驗。
其中 mPaaS 的 Hybrid 解決方案就包含前面提到:H5 容器、離線包、小程序 三大部分。
mPaaS H5 容器是一個移動端 Hybrid SDK,提供了良好的外部擴展,可結(jié)合具體業(yè)務(wù)需求定制 JSAPI。在 Android 上使用 UC Webview,擁有解決系統(tǒng)級 Webview Crash 的能力。
mPaaS H5 離線包將 HTML 靜態(tài)資源壓縮預置到客戶端或通過 WIFI 預加載到本地,使用時直接從本地加載,從而最大程度地提高性能。結(jié)合 mPaaS MDS 推送服務(wù),可以實現(xiàn)灰度發(fā)布、強制更新,讓業(yè)務(wù)的開發(fā)更加靈活。
mPaaS 小程序可以讓大家自己的 App 使用小程序技術(shù)開發(fā),構(gòu)建自己的 App 生態(tài),也就是說一步到位讓其滿足超級 App 的能力。由于底層使用的就是支付寶小程序的技術(shù),可以無縫遷移支付寶小程序到自己的 App 中。
目前支付寶小程序的 IDE 已經(jīng)支持多渠道,包括支付寶、mPaaS和釘釘,點擊切換即可輕松將小程序發(fā)布到對應(yīng)的平臺。
作者:云攻略小攻
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
ionic 是一個強大的 HTML5 應(yīng)用程序開發(fā)框架(HTML5 Hybrid Mobile App Framework )。 可以幫助您使用 Web 技術(shù),比如 HTML、CSS 和 Javascript 構(gòu)建接近原生體驗的移動應(yīng)用程序。
ionic 主要關(guān)注外觀和體驗,以及和你的應(yīng)用程序的 UI 交互,特別適合用于基于 Hybird 模式的 HTML5 移動應(yīng)用程序開發(fā)。
ionic是一個輕量的手機UI庫,具有速度快,界面現(xiàn)代化、美觀等特點。為了解決其他一些UI庫在手機上運行緩慢的問題,它直接放棄了IOS6和Android4.1以下的版本支持,來獲取更好的使用體驗。
ionic 特點
1.ionic 基于Angular語法,簡單易學。
2.ionic 是一個輕量級框架。
3.ionic 完美的融合下一代移動框架,支持 Angularjs 的特性, MVC ,代碼易維護。
4.ionic 提供了漂亮的設(shè)計,通過 SASS 構(gòu)建應(yīng)用程序,它提供了很多 UI 組件來幫助開發(fā)者開發(fā)強大的應(yīng)用。
5.ionic 專注原生,讓你看不出混合應(yīng)用和原生的區(qū)別
6.ionic 提供了強大的命令行工具。
7.ionic 性能優(yōu)越,運行速度快。
學習前你需要了解?
學習前你需要了解以下基礎(chǔ)知識:
HTML
CSS
Javascript
Angular
ionic 是一個強大的 HTML5 應(yīng)用程序開發(fā)框架(HTML5 Hybrid Mobile App Framework )。 可以幫助您使用 Web 技術(shù),比如 HTML、CSS 和 Javascript 構(gòu)建接近原生體驗的移動應(yīng)用程序。
ionic 主要關(guān)注外觀和體驗,以及和你的應(yīng)用程序的 UI 交互,特別適合用于基于 Hybird 模式的 HTML5 移動應(yīng)用程序開發(fā)。
ionic是一個輕量的手機UI庫,具有速度快,界面現(xiàn)代化、美觀等特點。為了解決其他一些UI庫在手機上運行緩慢的問題,它直接放棄了IOS6和Android4.1以下的版本支持,來獲取更好的使用體驗。
ionic 特點
1.ionic 基于Angular語法,簡單易學。
2.ionic 是一個輕量級框架。
3.ionic 完美的融合下一代移動框架,支持 Angularjs 的特性, MVC ,代碼易維護。
4.ionic 提供了漂亮的設(shè)計,通過 SASS 構(gòu)建應(yīng)用程序,它提供了很多 UI 組件來幫助開發(fā)者開發(fā)強大的應(yīng)用。
5.ionic 專注原生,讓你看不出混合應(yīng)用和原生的區(qū)別
6.ionic 提供了強大的命令行工具。
7.ionic 性能優(yōu)越,運行速度快。
學習本教程前你需要了解?
學習本教程前你需要了解以下基礎(chǔ)知識:
HTML
CSS
Javascript
Angular
ionic 相關(guān)內(nèi)容
ionic 官方網(wǎng)站:http://ionicframework.com/
ionic 官方文檔:http://ionicframework.com/docs/
Github 地址:https://github.com/driftyco/ionic
本站實例采用了ionic v1.3.2 版本,使用的 CDN 庫地址:
<link rel="stylesheet"> <script src="https://cdn.bootcss.com/ionic/1.3.2/js/ionic.bundle.min.js"></script>
ionic 最新版本下載地址:http://ionicframework.com/docs/overview/#download。
下載后解壓壓縮包,包含以下目錄:
css/ => 樣式文件 fonts/ => 字體文件 js/ => Javascript文件 version.json => 版本更新說明
你也可以在 Github 上下載以下資源文件:https://github.com/driftyco/ionic(在release 目錄中)。
接下來,我們只需要在項目中引入以上目錄中的 css/ionic.min.css 和 js/ionic.bundle.min.js 文件即可創(chuàng)建 ionic 應(yīng)用。
實例
<ion-header-barclass="bar-positive"><h1class="title">Hello World!</h1></ion-header-bar><ion-content><p>我的第一個 ionic 應(yīng)用。</p></ion-content>
嘗試一下 ?
點擊 "嘗試一下" 按鈕查看在線實例。
本教程著重講解 ionic 框架的應(yīng)用,大部分實例在瀏覽器中運行 ,移動設(shè)備上運行可以在接下來的命令行安裝教程中詳細了解。
注意:在移動應(yīng)用如 phonegap 中我們只需將對應(yīng)的 js 和 css 文件加入到資源庫中即可。
命令行安裝
首先您需要安裝 Node.js,我們在接下來的安裝中需要使用到其 NPM 工具,更多 NPM 介紹可以查看我們的NPM 使用介紹。
然后通過命令行工具安裝最新版本的 cordova 和 ionic 。通過參考Android 和 iOS 官方文檔來安裝。
Window 和 Linux 上打開命令行工具執(zhí)行以下命令:
$ npm install -g cordova ionic
Mac 系統(tǒng)上使用以下命令:
sudo npm install -g cordova ionic
提示: IOS需要在Mac Os X. 和Xcode環(huán)境下面安裝使用。
如果你已經(jīng)安裝了以上環(huán)境,可以執(zhí)行以下命令來更新版本:
npm update -g cordova ionic
或
sudo npm update -g cordova ionic
創(chuàng)建應(yīng)用
使用ionic官方提供的現(xiàn)成的應(yīng)用程序模板,或一個空白的項目創(chuàng)建一個ionic應(yīng)用:
$ ionic start myApp tabs
運行我們剛才創(chuàng)建的ionic項目
使用 ionic tool 創(chuàng)建,測試,運行你的apps(或者通過Cordova直接創(chuàng)建)。
創(chuàng)建Android應(yīng)用
$ cd myApp $ ionic platform add android $ ionic build android $ ionic emulate android
如果一切正常會彈出模擬器,界面如下所示:
創(chuàng)建iOS應(yīng)用
$ cd myApp $ ionic platform add ios $ ionic build ios $ ionic emulate ios
如果出現(xiàn)"ios-sim was not found."錯誤,可以執(zhí)行以下命令:
npm install -g ios-sim
如果一切正常會彈出模擬器,界面如下所示:
Ionic Lab
Ionic Lab 是桌面版的開發(fā)環(huán)境,如果你不喜歡使用命令行操作,Ionic Lab 將會滿足你的需求。
Ionic Lab 為開發(fā)者提供了一個更簡單的方法來開始,編譯,運行,和模擬運行Ionic的應(yīng)用程序。
Ionic Lab 支持的平臺有:Window、Mac OS X、Linux,下載地址為:http://lab.ionic.io/,下載后直接安裝即可。整個操作界面如下所示:
通過以上界面你可以完成以下操作:
創(chuàng)建應(yīng)用
預覽應(yīng)用
編譯應(yīng)用
運行應(yīng)用
上傳應(yīng)用
運行日志查看
……
推薦使用Sublime Text作為 Ionic 項目的編輯器,我們可以通過 Ionic Lab 直接在Sublime Text 上打開項目,如下圖:
Gif 操作演示
前面的章節(jié)中我們已經(jīng)學會了 ionic 框架如何導入到項目中。
接下來我們將為大家介紹如何創(chuàng)建一個 ionic APP 應(yīng)用。
ionic 創(chuàng)建 APP 使用 HTML、CSS 和 Javascript 來構(gòu)建,所以我們可以創(chuàng)建一個 www 目錄,并在目錄下創(chuàng)建 index.html 文件,代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo</title> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <script src="lib/ionic/js/ionic.bundle.js"></script> <!-- 在使用 Cordova/PhoneGap 創(chuàng)建的 APP 中包含的文件,由 Cordova/PhoneGap 提供,(開發(fā)過程中顯示 404) --> <script src="cordova.js"></script> </head> <body> </body> </html>
以上代碼中,我們引入了 Ionic CSS 文件、 Ionic JS 文件及 Ionic AngularJS 擴展ionic.bundle.js(ionic.bundle.js)。
ionic.bundle.js 文件已經(jīng)包含了 Ionic核心JS、AngularJS、Ionic的AngularJS擴展,如果你需要引入其他 Angular 模塊,可以從 lib/js/angular 目錄中調(diào)用。
cordova.js 是在使用 Cordova/PhoneGap 創(chuàng)建應(yīng)用時生成的,不需要手動引入,你可以在 Cordova/PhoneGap 項目中找到該文件,所以在開發(fā)過程中顯示 404 是正常的。
創(chuàng)建 APP
接下來我們來實現(xiàn)一個包含標題、側(cè)邊欄、列表等的應(yīng)用,設(shè)計圖如下:
創(chuàng)建側(cè)邊欄
側(cè)邊欄創(chuàng)建使用 ion-side-menus 控制器。
編輯我們先前創(chuàng)建的 index.html 文件,修改 <body> 內(nèi)的內(nèi)容,如下所示:
<body> <ion-side-menus> <ion-side-menu-content> </ion-side-menu-content> <ion-side-menu side="left"> </ion-side-menu> </ion-side-menus> </body>
控制器解析:
ion-side-menus: 是一個帶有邊欄菜單的容器,可以通過點擊按鈕或者滑動屏幕來展開菜單。
ion-side-menu-content:展示主要內(nèi)容的容器,可以通過滑動屏幕來展開menu。
ion-side-menu:存放側(cè)邊欄的容器。
初始化 APP
接下來我們創(chuàng)建一個新的 AngularJS 模塊,并初始化,代碼位于 www/js/app.js 中:
angular.module('todo', ['ionic'])
之后在我們的 body 標簽中添加 ng-app 屬性:
<body ng-app="todo">
在 index.html 文件的 <script src="cordova.js"></script> 上面引入 app.js 文件:
<script src="js/app.js"></script>
修改 index.html 文件 body 標簽的內(nèi)容,代碼如下所示:
<body ng-app="todo"> <ion-side-menus> <!-- 中心內(nèi)容 --> <ion-side-menu-content> <ion-header-bar class="bar-dark"> <h1 class="title">Todo</h1> </ion-header-bar> <ion-content> </ion-content> </ion-side-menu-content> <!-- 左側(cè)菜單 --> <ion-side-menu side="left"> <ion-header-bar class="bar-dark"> <h1 class="title">Projects</h1> </ion-header-bar> </ion-side-menu> </ion-side-menus> </body>
嘗試一下 ?
以上步驟我們已經(jīng)完成了 ionic 基本 APP 的應(yīng)用。
創(chuàng)建列表
首先創(chuàng)建一個控制器 TodoCtrl:
<body ng-app="todo" ng-controller="TodoCtrl">
在app.js文件中,使用控制器定義列表數(shù)據(jù):
angular.module('todo', ['ionic']) .controller('TodoCtrl', function($scope) { $scope.tasks = [ { title: '菜鳥教程' }, { title: 'www.runoob.com' }, { title: '菜鳥教程' }, { title: 'www.runoob.com' } ]; });
在index.html頁面中數(shù)據(jù)列表我們使用 Angular ng-repeat 來迭代數(shù)據(jù):
<!-- 中心內(nèi)容 --> <ion-side-menu-content> <ion-header-bar class="bar-dark"> <h1 class="title">Todo</h1> </ion-header-bar> <ion-content> <!-- 列表 --> <ion-list> <ion-item ng-repeat="task in tasks"> {{task.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu-content>
修改后 index.html body 標簽內(nèi)代碼如下:
<body ng-app="todo" ng-controller="TodoCtrl"> <ion-side-menus> <!-- 中心內(nèi)容 --> <ion-side-menu-content> <ion-header-bar class="bar-dark"> <h1 class="title">Todo</h1> </ion-header-bar> <ion-content> <!-- 列表 --> <ion-list> <ion-item ng-repeat="task in tasks"> {{task.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu-content> <!-- 左側(cè)菜單 --> <ion-side-menu side="left"> <ion-header-bar class="bar-dark"> <h1 class="title">Projects</h1> </ion-header-bar> </ion-side-menu> </ion-side-menus> <script src="http://www.runoob.com/static/ionic/js/app.js"></script> <script src="cordova.js"></script> </body>
嘗試一下 ?
創(chuàng)建添加頁面
修改 index.html 在 </ion-side-menus> 后添加如下代碼:
<script id="new-task.html" type="text/ng-template"> <div class="modal"> <!-- Modal header bar --> <ion-header-bar class="bar-secondary"> <h1 class="title">New Task</h1> <button class="button button-clear button-positive" ng-click="closeNewTask()">Cancel</button> </ion-header-bar> <!-- Modal content area --> <ion-content> <form ng-submit="createTask(task)"> <div class="list"> <label class="item item-input"> <input type="text" placeholder="What do you need to do?" ng-model="task.title"> </label> </div> <div class="padding"> <button type="submit" class="button button-block button-positive">Create Task</button> </div> </form> </ion-content> </div> </script>
以上代碼中我們通過 <script id="new-task.html" type="text/ng-template"> 定義了新的模板頁面。
表單提交時觸發(fā) createTask(task) 函數(shù)。
ng-model="task.title" 會將表單的輸入數(shù)據(jù)賦值給 task 對象的 title 屬性。
修改 <ion-side-menu-content> 內(nèi)的內(nèi)容,代碼如下:
<!-- 中心內(nèi)容 --> <ion-side-menu-content> <ion-header-bar class="bar-dark"> <h1 class="title">Todo</h1> <!-- 新增按鈕--> <button class="button button-icon" ng-click="newTask()"> <i class="icon ion-compose"></i> </button> </ion-header-bar> <ion-content> <!-- 列表 --> <ion-list> <ion-item ng-repeat="task in tasks"> {{task.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu-content>
app.js 文件中,控制器代碼如下:
angular.module('todo', ['ionic']) .controller('TodoCtrl', function($scope, $ionicModal) { $scope.tasks = [ { title: '菜鳥教程' }, { title: 'www.runoob.com' }, { title: '菜鳥教程' }, { title: 'www.runoob.com' } ]; // 創(chuàng)建并載入模型 $ionicModal.fromTemplateUrl('new-task.html', function(modal) { $scope.taskModal = modal; }, { scope: $scope, animation: 'slide-in-up' }); // 表單提交時調(diào)用 $scope.createTask = function(task) { $scope.tasks.push({ title: task.title }); $scope.taskModal.hide(); task.title = ""; }; // 打開新增的模型 $scope.newTask = function() { $scope.taskModal.show(); }; // 關(guān)閉新增的模型 $scope.closeNewTask = function() { $scope.taskModal.hide(); }; });
創(chuàng)建側(cè)邊欄
通過以上步驟我們已經(jīng)實現(xiàn)了新增功能,現(xiàn)在我們?yōu)?app 添加側(cè)邊欄功能。
修改 <ion-side-menu-content> 內(nèi)的內(nèi)容,代碼如下:
<!-- 中心內(nèi)容 --> <ion-side-menu-content> <ion-header-bar class="bar-dark"> <button class="button button-icon" ng-click="toggleProjects()"> <i class="icon ion-navicon"></i> </button> <h1 class="title">{{activeProject.title}}</h1> <!-- 新增按鈕 --> <button class="button button-icon" ng-click="newTask()"> <i class="icon ion-compose"></i> </button> </ion-header-bar> <ion-content scroll="false"> <ion-list> <ion-item ng-repeat="task in activeProject.tasks"> {{task.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu-content>
添加側(cè)邊欄:
<!-- 左邊欄 --> <ion-side-menu side="left"> <ion-header-bar class="bar-dark"> <h1 class="title">Projects</h1> <button class="button button-icon ion-plus" ng-click="newProject()"> </button> </ion-header-bar> <ion-content scroll="false"> <ion-list> <ion-item ng-repeat="project in projects" ng-click="selectProject(project, $index)" ng-class="{active: activeProject == project}"> {{project.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu>
<ion-item> 中的 ng-class 指令設(shè)置菜單激活樣式。
這里我們創(chuàng)建一個新的js 文件 app2.js(為了不與前面的混淆),代碼如下:
angular.module('todo', ['ionic']) /** * The Projects factory handles saving and loading projects * from local storage, and also lets us save and load the * last active project index. */ .factory('Projects', function() { return { all: function() { var projectString = window.localStorage['projects']; if(projectString) { return angular.fromJson(projectString); } return []; }, save: function(projects) { window.localStorage['projects'] = angular.toJson(projects); }, newProject: function(projectTitle) { // Add a new project return { title: projectTitle, tasks: [] }; }, getLastActiveIndex: function() { return parseInt(window.localStorage['lastActiveProject']) || 0; }, setLastActiveIndex: function(index) { window.localStorage['lastActiveProject'] = index; } } }) .controller('TodoCtrl', function($scope, $timeout, $ionicModal, Projects, $ionicSideMenuDelegate) { // A utility function for creating a new project // with the given projectTitle var createProject = function(projectTitle) { var newProject = Projects.newProject(projectTitle); $scope.projects.push(newProject); Projects.save($scope.projects); $scope.selectProject(newProject, $scope.projects.length-1); } // Load or initialize projects $scope.projects = Projects.all(); // Grab the last active, or the first project $scope.activeProject = $scope.projects[Projects.getLastActiveIndex()]; // Called to create a new project $scope.newProject = function() { var projectTitle = prompt('Project name'); if(projectTitle) { createProject(projectTitle); } }; // Called to select the given project $scope.selectProject = function(project, index) { $scope.activeProject = project; Projects.setLastActiveIndex(index); $ionicSideMenuDelegate.toggleLeft(false); }; // Create our modal $ionicModal.fromTemplateUrl('new-task.html', function(modal) { $scope.taskModal = modal; }, { scope: $scope }); $scope.createTask = function(task) { if(!$scope.activeProject || !task) { return; } $scope.activeProject.tasks.push({ title: task.title }); $scope.taskModal.hide(); // Inefficient, but save all the projects Projects.save($scope.projects); task.title = ""; }; $scope.newTask = function() { $scope.taskModal.show(); }; $scope.closeNewTask = function() { $scope.taskModal.hide(); } $scope.toggleProjects = function() { $ionicSideMenuDelegate.toggleLeft(); }; // Try to create the first project, make sure to defer // this by using $timeout so everything is initialized // properly $timeout(function() { if($scope.projects.length == 0) { while(true) { var projectTitle = prompt('Your first project title:'); if(projectTitle) { createProject(projectTitle); break; } } } }); });
body 中 ion-side-menus 代碼如下::
<ion-side-menus> <!-- 中心內(nèi)容 --> <ion-side-menu-content> <ion-header-bar class="bar-dark"> <button class="button button-icon" ng-click="toggleProjects()"> <i class="icon ion-navicon"></i> </button> <h1 class="title">{{activeProject.title}}</h1> <!-- 新增按鈕 --> <button class="button button-icon" ng-click="newTask()"> <i class="icon ion-compose"></i> </button> </ion-header-bar> <ion-content scroll="false"> <ion-list> <ion-item ng-repeat="task in activeProject.tasks"> {{task.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu-content> <!-- 左邊欄 --> <ion-side-menu side="left"> <ion-header-bar class="bar-dark"> <h1 class="title">Projects</h1> <button class="button button-icon ion-plus" ng-click="newProject()"> </button> </ion-header-bar> <ion-content scroll="false"> <ion-list> <ion-item ng-repeat="project in projects" ng-click="selectProject(project, $index)" ng-class="{active: activeProject == project}"> {{project.title}} </ion-item> </ion-list> </ion-content> </ion-side-menu> </ion-side-menus>
嘗試一下 ?
Header(頭部)
Header是固定在屏幕頂部的組件,可以包如標題和左右的功能按鈕。
ionic 默認提供了許多種顏色樣式,你可以調(diào)用不同的樣式名,當然也可以自定義一個。
bar-light
<div class="bar bar-header bar-light"> <h1 class="title">bar-light</h1></div>
嘗試一下 ?
bar-stable
<div class="bar bar-header bar-stable"> <h1 class="title">bar-stable</h1></div>
嘗試一下 ?
bar-positive
<div class="bar bar-header bar-positive"> <h1 class="title">bar-positive</h1></div>
嘗試一下 ?
bar-calm
<div class="bar bar-header bar-calm"> <h1 class="title">bar-calm</h1></div>
嘗試一下 ?
bar-balanced
<div class="bar bar-header bar-balanced"> <h1 class="title">bar-balanced</h1></div>
嘗試一下 ?
bar-energized
<div class="bar bar-header bar-energized"> <h1 class="title">bar-energized</h1></div>
嘗試一下 ?
bar-assertive
<div class="bar bar-header bar-assertive"> <h1 class="title">bar-assertive</h1></div>
嘗試一下 ?
bar-royal
<div class="bar bar-header bar-royal"> <h1 class="title">bar-royal</h1></div>
嘗試一下 ?
bar-dark
<div class="bar bar-header bar-dark"> <h1 class="title">bar-dark</h1></div>
嘗試一下 ?
Sub Header(副標題)
Sub Header同樣是固定在頂部,只是是在Header的下面,就算沒有寫Header這個,Sub Header這個樣式也會距離頂部有一個Header的距離。顏色樣式同 Header 。
<div class="bar bar-header"> <h1 class="title">Header</h1></div><div class="bar bar-subheader"> <h2 class="title">Sub Header</h2></div>
嘗試一下 ?
Footer(底部)
Footer 是在屏幕的最下方,可以包含多種內(nèi)容類型。
<div class="bar bar-footer bar-balanced"> <div class="title">Footer</div></div>
嘗試一下 ?
Footer 同上面的 Header,只是把樣式名 bar-header 換做 bar-footer 。
<div class="bar bar-footer"> <button class="button button-clear">Left</button> <div class="title">Title</div> <button class="button button-clear">Right</button></div>
嘗試一下 ?
此外,如果底部沒有標題,但是又需要右邊的按鈕,你需要在右側(cè)按鈕添加 pull-right如:
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。