前 mPaaS H5 容器 Demo 源码已发布至 GitHub,全新的接入方式让你可以一键集成 mPaaS 环境并快速接入 H5 容器,体验统一的容器和内核,获取媲美原生的 Hybrid 方案及完美的动态能力。
目前支付宝有 2 套 Hybrid 方案: HTML5 容器与小程序。小程序是最近几年才出来,H5 容器已经有了很长时间的历史,所以我们就先从 H5 容器说起。
在支付宝中,HTML5 容器架构如图所示:
最上层是浏览器,这块就是大家常见的 Web 开发环境,包括 HTML、CSS、JavaScript等。H5 容器作为中间层,将浏览器和支付宝底层框架有机结合起来,在 H5 容器里面有 2 个非常重要的概念: JSBridge 和 离线包,后面会做详细介绍。支付宝底层框架会给 H5 容器提供 Native 的能力,这其中就包括 RPC(远程过程调用,用来实现 APP 和服务器通信)、支付、扫一扫等。
JSBridge 是 H5 容器的基石,桥接了 JS 环境与 Native,实现了 Native 代码和 浏览器 环境的双向通信,Native 代码可以通过调用 浏览器 提供的接口运行JS,从而实现调用 JS 函数、传递参数到 JS 环境等;而浏览器到JS环境的通信是通过 Native 拦截浏览器的请求来实现,请求可以是网络请求或者是一些内部函数的调用。
那么 JSBridge 会带来什么好处呢,在传统的 Web 开发场景,H5 页面会通过 HTTP 的 GET 或者 POST 请求到后台获取数据,就会用到 jQuery 等 AJAX 框架。但是 H5 页面中的 JS 函数公开的,没法做一些加密逻辑,同时对于无法优化网络。这几年随着 4G 和流量卡的普及,让手机网络变得更快、更便宜,在这之前大量用户会面临流量不足、信号差、网络不稳定的情况,这些场景在现在依然存在,而纯 Web 方案是没法提供相关的优化。
H5 容器提供的 JSBridge 解决了这个问题,所有 H5 页面需要从后台获取的数据都通过 JS Bridge 调用 Native 的 RPC SDK 来获取。这样实际 App 请求的数据都是由 RPC SDK 来发送,从而可以实现安全加密、签名校验、弱网优化、流量优化的功能。Native 层的这些功能是 Web 页面开发人员无感知的,所以业务开发人员只需要专注其自身的业务开发即可。安全性由支付宝底层 SDK 保障。
H5 容器提供了 2 种扩展方式:
1. JSAPI
JSAPI 方式给 H5 页面增加了 Native 功能调用接口,通过实现自定义 JSAPI 类中的 handler 方式,可以以 Native 的形式实现特定功能,例如调用 Native 加密函数。
2. 事件
H5 容器在状态变化时会发送事件,通过监听 H5 容器特定事件,可以实现对 H5 容器生命周期的处理,比如修改加载进度条颜色、修改页面导航栏等。事件提供了更强的定制性,完全可以满足对 H5 容器的各种自定义需求。
H5 容器离线包是 H5 容器用户体验的关键。
在 APP 里面打开一个线上页面的时候,通常会有一个白屏的阶段,这是浏览器需要从服务器下载 HTML 资源。由于手机网络的限制,这个时间会很不确定,通常会花费 300ms 以上的时间,用户在这个时间里面就会看到页面白屏。
为了优化 H5 容器用户体验,减少白屏时间,支付宝在 H5 容器中引入了离线包技术。离线包可以简单理解为一个 zip 压缩包,其中包含前端页面所需的 HTML、CSS、JS、图片等资源。内置到客户端后,H5 容器打开离线包页面时会直接从离线包中获取资源,这个是毫秒的访问时间,消除了打开页面白屏现象。
在支付宝中,离线包分为 2 种:普通的业务资源包和公共资源包。先说公共资源包吧,公共资源包中会包含一些框架 JS、CSS、常见图片等,这些资源在整个 App 里面就只保存一份;而业务资源包中只保存该业务所需的页面静态资源,业务之间是相互独立解耦的。这样一个业务的页面资源就会同时来自其业务资源包和公共资源包,公共资源包的存在优化了 App 大小。
为了满足快速发布的需求,H5 容器离线包提供了更新机制,以单个离线包作为更新维度。因为单个离线包业务很简单,所以离线包的大小是可控的,通常小于 500KB,这样单个离线包的更新时间可控,可以做到用户无感知。在一些极端网络场景下,新的业务资源包没有更新超过,而我们又期望用户使用的是最新的业务,这个时候 fallback 访问机制就会发挥作用。每个离线包资源都会在服务器存放一份,在刚刚说到的极端场景下,用户会访问服务器的 fallback 地址获取资源,从而保障页面可用。
结合前面说到的离线包后,整个 H5 容器渲染流程如下。其中离线包资源的更新、下载对用户无感知,页面访问的资源是来自离线包还是来自 fallback 地址对前端是无感知的。
为了提高 H5 容器稳定性,支付宝在安卓系统上使用了 UC Webview,UC Webview 的崩溃率和ANR率远低于系统浏览器,而且彻底规避了安卓系统 Webview 碎片化问题,相信做过安卓前端页面兼容的同学一定可以体会到使用一个浏览器内核的好处。
H5 容器作为一个成熟的 Hybrid 方案可以满足大部分的业务场景需求,但是其依然存在一些局限性。H5 容器的业务开发部分还保持着前端开发思维,毕竟整个过程都是使用的前端技术,只需要在业务开发完成后集成到 APP 中完成测试。但是客户端开发其中还有很多关键的概念,例如 iOS 的 ViewController 、Android 的 Activity 等,对客户端页面栈有清楚的了解更有助于开发 H5 容器。同时 H5 容器还存在一个致命的问题就是无法管控质量,宽泛的前端规范让管控变得异常困难。
为了解决 H5 容器的局限性,顺应当前 APP 共享开放的需求,支付宝推出了新的 Hybrid 方案:支付宝小程序。支付宝小程序一种全新的开放模式,它运行在支付宝客户端,可以被便捷地获取和传播,为终端用户提供更优的用户体验 。支付宝小程序基于 Web 技术,因此学习成本低;其一套代码同时支持 iOS 和 Android;并提供了丰富组件和 API;完全为 APP 开发而生。目前支付宝小程序已经提供 2000 多个开放接口,API 日调用次数超过 25 亿次,拥有超过 100 万的合作伙伴和超过 10 万个活跃服务商。
支付宝小程序同时还支持了阿里系多个 App ,包括口碑、高德和钉钉。
那么支付宝小程序是怎么解决 H5 容器的局限性呢?首先支付宝小程序是基于一个定制的 DSL 语言,不是前端的标准,但是类似。在 DSL 规则下业务进行小程序的开发,不支持直接操作 DOM,这种 DSL 规则下的自由可以有效的进行质量管控。另外支付宝小程序可以提供比 H5 小程序更优秀的性能、体验和兼容性,可以无感替换底层框架,应对遇到的性能问题。
目前支付宝小程序也支持前面提到的 H5 容器所使用的离线包技术,同时也支持 JSAPI 和事件的扩展方式,提供了更大的灵活性。
支付宝小程序的 DSL 语言包括了 4 部分:
文件用来提供小程序相关的配置,这里就强调了 page 和 window 的概念,支持用户去配置导航栏等 APP 开发中的概念。
可以理解为小孩程序的页面 HTML,不支持直接操作 DOM 保障了页面逻辑的可控。
用来描述代码逻辑,提供了 Page 中所需的各种生命周期,让开发者有APP 中的各种概念。
类似于 H5 中的 CSS,支持大部分 CSS 语法,让前端开发可以快速完成小程序 UI 设计。
目前支付宝小程序已经逐步开放给个人开发者使用,大家可以申请开通,享受支付宝带来的流量。
支付宝沉淀的 Hybrid 方案 H5 容器和小程序已经经过实际严苛的业务考验,通过前面的介绍相信大家已经有了了解。
从 0 开始开发一套 Hybrid 框架需要大量的人力以及反复的业务验证,对于大部分公司来说成本太高。
而使用开源的 Hybrid 框架,例如 Cordova、Weex、React Native、Flutter等会面临一个非常致命的问题,就是遇到框架层的问题,很难获得及时有效的技术支持。
目前支付宝的 Hybrid 方案已经借助移动开发平台 mPaaS 对外输出,解决前面提到的痛点,让你直接和支付宝使用同一套框架层代码,而且提供及时的技术支持。
mPaaS 是一站式移动开发解决方案,提供了移动开发所需的 5 大组件:MGS、MDS、MPS、MAS、MSS,这些组件都是基于支付宝,经过实际业务考验。
其中 mPaaS 的 Hybrid 解决方案就包含前面提到:H5 容器、离线包、小程序 三大部分。
mPaaS H5 容器是一个移动端 Hybrid SDK,提供了良好的外部扩展,可结合具体业务需求定制 JSAPI。在 Android 上使用 UC Webview,拥有解决系统级 Webview Crash 的能力。
mPaaS H5 离线包将 HTML 静态资源压缩预置到客户端或通过 WIFI 预加载到本地,使用时直接从本地加载,从而最大程度地提高性能。结合 mPaaS MDS 推送服务,可以实现灰度发布、强制更新,让业务的开发更加灵活。
mPaaS 小程序可以让大家自己的 App 使用小程序技术开发,构建自己的 App 生态,也就是说一步到位让其满足超级 App 的能力。由于底层使用的就是支付宝小程序的技术,可以无缝迁移支付宝小程序到自己的 App 中。
目前支付宝小程序的 IDE 已经支持多渠道,包括支付宝、mPaaS和钉钉,点击切换即可轻松将小程序发布到对应的平台。
作者:云攻略小攻
本文为阿里云原创内容,未经允许不得转载。
ionic 是一个强大的 HTML5 应用程序开发框架(HTML5 Hybrid Mobile App Framework )。 可以帮助您使用 Web 技术,比如 HTML、CSS 和 Javascript 构建接近原生体验的移动应用程序。
ionic 主要关注外观和体验,以及和你的应用程序的 UI 交互,特别适合用于基于 Hybird 模式的 HTML5 移动应用程序开发。
ionic是一个轻量的手机UI库,具有速度快,界面现代化、美观等特点。为了解决其他一些UI库在手机上运行缓慢的问题,它直接放弃了IOS6和Android4.1以下的版本支持,来获取更好的使用体验。
ionic 特点
1.ionic 基于Angular语法,简单易学。
2.ionic 是一个轻量级框架。
3.ionic 完美的融合下一代移动框架,支持 Angularjs 的特性, MVC ,代码易维护。
4.ionic 提供了漂亮的设计,通过 SASS 构建应用程序,它提供了很多 UI 组件来帮助开发者开发强大的应用。
5.ionic 专注原生,让你看不出混合应用和原生的区别
6.ionic 提供了强大的命令行工具。
7.ionic 性能优越,运行速度快。
学习前你需要了解?
学习前你需要了解以下基础知识:
HTML
CSS
Javascript
Angular
ionic 是一个强大的 HTML5 应用程序开发框架(HTML5 Hybrid Mobile App Framework )。 可以帮助您使用 Web 技术,比如 HTML、CSS 和 Javascript 构建接近原生体验的移动应用程序。
ionic 主要关注外观和体验,以及和你的应用程序的 UI 交互,特别适合用于基于 Hybird 模式的 HTML5 移动应用程序开发。
ionic是一个轻量的手机UI库,具有速度快,界面现代化、美观等特点。为了解决其他一些UI库在手机上运行缓慢的问题,它直接放弃了IOS6和Android4.1以下的版本支持,来获取更好的使用体验。
ionic 特点
1.ionic 基于Angular语法,简单易学。
2.ionic 是一个轻量级框架。
3.ionic 完美的融合下一代移动框架,支持 Angularjs 的特性, MVC ,代码易维护。
4.ionic 提供了漂亮的设计,通过 SASS 构建应用程序,它提供了很多 UI 组件来帮助开发者开发强大的应用。
5.ionic 专注原生,让你看不出混合应用和原生的区别
6.ionic 提供了强大的命令行工具。
7.ionic 性能优越,运行速度快。
学习本教程前你需要了解?
学习本教程前你需要了解以下基础知识:
HTML
CSS
Javascript
Angular
ionic 相关内容
ionic 官方网站:http://ionicframework.com/
ionic 官方文档:http://ionicframework.com/docs/
Github 地址:https://github.com/driftyco/ionic
本站实例采用了ionic v1.3.2 版本,使用的 CDN 库地址:
<link href="https://cdn.bootcss.com/ionic/1.3.2/css/ionic.css" 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 文件即可创建 ionic 应用。
实例
<ion-header-barclass="bar-positive"><h1class="title">Hello World!</h1></ion-header-bar><ion-content><p>我的第一个 ionic 应用。</p></ion-content>
尝试一下 »
点击 "尝试一下" 按钮查看在线实例。
本教程着重讲解 ionic 框架的应用,大部分实例在浏览器中运行 ,移动设备上运行可以在接下来的命令行安装教程中详细了解。
注意:在移动应用如 phonegap 中我们只需将对应的 js 和 css 文件加入到资源库中即可。
命令行安装
首先您需要安装 Node.js,我们在接下来的安装中需要使用到其 NPM 工具,更多 NPM 介绍可以查看我们的NPM 使用介绍。
然后通过命令行工具安装最新版本的 cordova 和 ionic 。通过参考Android 和 iOS 官方文档来安装。
Window 和 Linux 上打开命令行工具执行以下命令:
$ npm install -g cordova ionic
Mac 系统上使用以下命令:
sudo npm install -g cordova ionic
提示: IOS需要在Mac Os X. 和Xcode环境下面安装使用。
如果你已经安装了以上环境,可以执行以下命令来更新版本:
npm update -g cordova ionic
或
sudo npm update -g cordova ionic
创建应用
使用ionic官方提供的现成的应用程序模板,或一个空白的项目创建一个ionic应用:
$ ionic start myApp tabs
运行我们刚才创建的ionic项目
使用 ionic tool 创建,测试,运行你的apps(或者通过Cordova直接创建)。
创建Android应用
$ cd myApp $ ionic platform add android $ ionic build android $ ionic emulate android
如果一切正常会弹出模拟器,界面如下所示:
创建iOS应用
$ cd myApp $ ionic platform add ios $ ionic build ios $ ionic emulate ios
如果出现"ios-sim was not found."错误,可以执行以下命令:
npm install -g ios-sim
如果一切正常会弹出模拟器,界面如下所示:
Ionic Lab
Ionic Lab 是桌面版的开发环境,如果你不喜欢使用命令行操作,Ionic Lab 将会满足你的需求。
Ionic Lab 为开发者提供了一个更简单的方法来开始,编译,运行,和模拟运行Ionic的应用程序。
Ionic Lab 支持的平台有:Window、Mac OS X、Linux,下载地址为:http://lab.ionic.io/,下载后直接安装即可。整个操作界面如下所示:
通过以上界面你可以完成以下操作:
创建应用
预览应用
编译应用
运行应用
上传应用
运行日志查看
……
推荐使用Sublime Text作为 Ionic 项目的编辑器,我们可以通过 Ionic Lab 直接在Sublime Text 上打开项目,如下图:
Gif 操作演示
前面的章节中我们已经学会了 ionic 框架如何导入到项目中。
接下来我们将为大家介绍如何创建一个 ionic APP 应用。
ionic 创建 APP 使用 HTML、CSS 和 Javascript 来构建,所以我们可以创建一个 www 目录,并在目录下创建 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 创建的 APP 中包含的文件,由 Cordova/PhoneGap 提供,(开发过程中显示 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 文件已经包含了 Ionic核心JS、AngularJS、Ionic的AngularJS扩展,如果你需要引入其他 Angular 模块,可以从 lib/js/angular 目录中调用。
cordova.js 是在使用 Cordova/PhoneGap 创建应用时生成的,不需要手动引入,你可以在 Cordova/PhoneGap 项目中找到该文件,所以在开发过程中显示 404 是正常的。
创建 APP
接下来我们来实现一个包含标题、侧边栏、列表等的应用,设计图如下:
创建侧边栏
侧边栏创建使用 ion-side-menus 控制器。
编辑我们先前创建的 index.html 文件,修改 <body> 内的内容,如下所示:
<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:展示主要内容的容器,可以通过滑动屏幕来展开menu。
ion-side-menu:存放侧边栏的容器。
初始化 APP
接下来我们创建一个新的 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 标签的内容,代码如下所示:
<body ng-app="todo"> <ion-side-menus> <!-- 中心内容 --> <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> <!-- 左侧菜单 --> <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>
尝试一下 »
以上步骤我们已经完成了 ionic 基本 APP 的应用。
创建列表
首先创建一个控制器 TodoCtrl:
<body ng-app="todo" ng-controller="TodoCtrl">
在app.js文件中,使用控制器定义列表数据:
angular.module('todo', ['ionic']) .controller('TodoCtrl', function($scope) { $scope.tasks = [ { title: '菜鸟教程' }, { title: 'www.runoob.com' }, { title: '菜鸟教程' }, { title: 'www.runoob.com' } ]; });
在index.html页面中数据列表我们使用 Angular ng-repeat 来迭代数据:
<!-- 中心内容 --> <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 标签内代码如下:
<body ng-app="todo" ng-controller="TodoCtrl"> <ion-side-menus> <!-- 中心内容 --> <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> <!-- 左侧菜单 --> <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>
尝试一下 »
创建添加页面
修改 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"> 定义了新的模板页面。
表单提交时触发 createTask(task) 函数。
ng-model="task.title" 会将表单的输入数据赋值给 task 对象的 title 属性。
修改 <ion-side-menu-content> 内的内容,代码如下:
<!-- 中心内容 --> <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' } ]; // 创建并载入模型 $ionicModal.fromTemplateUrl('new-task.html', function(modal) { $scope.taskModal = modal; }, { scope: $scope, animation: 'slide-in-up' }); // 表单提交时调用 $scope.createTask = function(task) { $scope.tasks.push({ title: task.title }); $scope.taskModal.hide(); task.title = ""; }; // 打开新增的模型 $scope.newTask = function() { $scope.taskModal.show(); }; // 关闭新增的模型 $scope.closeNewTask = function() { $scope.taskModal.hide(); }; });
创建侧边栏
通过以上步骤我们已经实现了新增功能,现在我们为 app 添加侧边栏功能。
修改 <ion-side-menu-content> 内的内容,代码如下:
<!-- 中心内容 --> <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-item> 中的 ng-class 指令设置菜单激活样式。
这里我们创建一个新的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> <!-- 中心内容 --> <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 默认提供了许多种颜色样式,你可以调用不同的样式名,当然也可以自定义一个。
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 是在屏幕的最下方,可以包含多种内容类型。
<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>
尝试一下 »
此外,如果底部没有标题,但是又需要右边的按钮,你需要在右侧按钮添加 pull-right如:
*请认真填写需求信息,我们会在24小时内与您取得联系。