构建实时、多平台的移动应用程序:使用 Ionic 框架和 Firebase 的示例

已发表: 2022-03-11

公司在制作智能手机应用程序时遇到的主要问题之一是跨不同平台构建本机应用程序的成倍成本。 虽然精明的前端开发人员已经开始开发几个有望帮助解决此问题的混合平台,但 Ionic Framework 和 Firebase 是动态组合,它们共同确实为我们使用 JavaScript 和 HTML5 构建实时智能手机应用程序提供了惊人的灵活性.

本教程介绍了这些多平台移动开发工具的功能,甚至提供了一些 Ionic 和 Firebase 示例。

结合起来,Ionic 和 Firebase 是一个很棒的多平台开发解决方案。

(注意:本文假设您熟悉 AngularJS 框架的基础知识。对于没有该背景的人来说,这是一篇关于 AngularJS 的精彩介绍性文章。)

介绍离子框架

Ionic 框架由三个主要组件组成:

  1. 为移动 UI 设计和优化的基于 SASS 的 UI 框架。
  2. AngularJS 前端 JavaScript 框架,用于快速构建可扩展且快速的应用程序。
  3. 带有 CSS、HTML 和 JavaScript 的原生移动应用程序的编译器(Cordova 或 PhoneGap)。

Ionic 框架还包含许多开箱即用的有用 CSS 组件。

感谢 Ionic 提供了大量的文档、示例和入门视频,以帮助简化学习曲线并让开发人员快速启动和运行。

介绍 Firebase

Firebase 是一种后端即服务的无模式数据系统,可提供实时数据同步,无需编写任何自定义代码。 Firebase 使您的大部分后端开发变得过时,从而显着减少了多平台开发时间。

主要特点和优势包括:

  1. 无需更改代码即可更改数据。 所有数据更改都会立即发布给客户端,无需任何后端代码修改。
  2. 很多适配器。 有适用于所有流行 JavaScript 框架和移动平台 SDK 的适配器,具有良好的支持和文档。 (在本文中,我们使用了 AngularFire,它是 Firebase 的 AngularJS 绑定。)
  3. 易于认证。 Firebase 中的身份验证就像单个方法调用一样简单,而与身份验证方法无关。 支持简单的电子邮件和密码、基于 Google、Facebook、Twitter 或 Github 的登录。
  4. 已启用离线。 所有 Firebase 数据都已启用离线功能,因此应用程序可以在断开连接模式下完全(或接近完全)运行。 当连接恢复时,应用程序会自动同步。
  5. 配置仪表板。 Firebase 的大部分内容(例如安全规则)都可以通过 Firebase 直观的仪表板界面轻松配置。
  6. 以 JSON 为中心。 在 Firebase 中,所有数据都以 JSON 对象的形式存储和检索。

Firebase 还提供用于托管前端代码的云服务,这可以节省大量部署和维护时间。

还值得注意的是,Firebase 在去年 10 月被谷歌收购,这给了它更多的关注和知名度。

一个简单的用例示例:费用跟踪

室友经常分担费用,并在需要时相互依赖。 所以,让我们帮助室友跟踪他们的开支,并帮助他们在月底进行核对。

为了让事情变得更有趣,让我们构建一个多平台移动应用程序,该应用程序将提供实时更新,这样他们就可以监控发生的费用。

这个 Ionic 和 Firebase 示例演示了流畅的多平台应用程序开发。

现在我们已经决定要构建什么并且我们已经了解了这些工具,让我们开始吧!

Ionic 和 Firebase 入门

我们需要做的第一件事是安装 Ionic。 按照 Ionic 入门页面上提供的安装说明进行操作。 (请注意,Ionic 依赖于 NodeJS,因此如果您的机器上还没有它,说明将要求您也安装它)。

AngularFire 5 分钟教程是开始熟悉 Firebase 的好地方。 如果您像我一样是“修补匠”或触觉学习者,您可能希望从 GitHub 中提取我的实现并开始使用代码。

编码我们的多平台应用程序

对于本教程,我们将使用作为 Ionic 安装的一部分提供的示例tabs应用程序作为我们应用程序的基础。 (您可以使用命令ionic start myApp tabs运行示例应用程序。)

在您最喜欢的 IDE(我正在使用 Webstorm)中打开示例tabs应用程序,让我们开始修改它以构建我们的室友应用程序。

对于我们的示例 Ionic 和 Firebase 应用程序,我们将需要以下三个屏幕:

离子/Firebase 屏幕 1离子/Firebase 屏幕 2Ionic/Firebase 屏幕 3

在创建这些屏幕之前,让我们删除示例应用程序默认提供的“朋友详细信息屏幕”,如下所示:

  1. 删除www/templates/friend-detail.html文件。
  2. www/js/app.js中,删除(或注释掉) friend-detail.html的状态。
  3. www/js/controllers.js中,删除在我们删除的状态中引用的FriendDetailCtrl控制器。

现在让我们将屏幕底部的选项卡选择器的图标和文本更改为以下内容:

使用 Ionic 框架的示例代码更改图标和选项卡文本。

这只需在www/templates/tabs.html中进行以下更改即可完成:

 <ion-tabs class="tabs-icon-top"> <!-- My Tab --> <ion-tab title="My Expense" icon="icon ion-log-in" href="#/tab/dash"> <ion-nav-view name="tab-dash"></ion-nav-view> </ion-tab> <!-- Friends Tab --> <ion-tab title="Roomie's" icon="icon ion-log-out" href="#/tab/friends"> <ion-nav-view name="tab-friends"></ion-nav-view> </ion-tab> <!-- Account --> <ion-tab title="Account" icon="icon ion-ios7-gear" href="#/tab/account"> <ion-nav-view name="tab-account"></ion-nav-view> </ion-tab> </ion-tabs>

在我们将数据连接到 Firebase 之前,让我们通过将以下代码添加到www/templates/tab-dash.html expenses创建一个列表并将其绑定到一个名为 costs 的数组:

 <ion-view title="My Expenses"> <ion-content> <ion-list> <ion-item ng-repeat="expense in expenses|filter:user.password.email" type="item-text-wrap"> {{expense.label}} <span class="badge badge-balanced">{{expense.cost}}</span> </ion-item> </ion-list> <div class="card assertive"> <div class="item item-text-wrap"> Total Spent <span class="badge badge-positive">{{getTotal()}}</span> </div> </div> </ion-content> <ion-footer-bar> <input ng-model='label' type='text' placeholder='Type a new expense...' /> <input ng-model='cost' type="number" placeholder='$' /> <button class="button icon-left ion-plus" ng-click="addExpense($event)">Add</button> </ion-footer-bar> </ion-view>

我们还需要扩展www/js/controllers.js中的DashCtrl以包含expenses数组,以及addExpense方法和getTotal方法,如下所示:

 .controller('DashCtrl', function($scope) { $scope.expenses = [{ by: 'email', label: 'test', cost: 10 }]; $scope.addExpense = function(e) { $scope.expenses.push({ by: < some email > label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function() { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })

expenses数组存储费用列表中的项目, addExpense()方法向expenses数组添加一个新值, getTotal()方法为我们提供数组中所有项目的总和。

现在需要对tab-friends.html进行一组类似的更改。 尝试自己执行此操作,但如果遇到问题,或者想验证您是否正确执行此操作,可以参考我在 GitHub 上的实现。

在 Firebase 中挂钩

您将需要一个 Firebase 帐户。 您可以在此处注册免费的 Firebase“黑客计划”。

注册后,您将收到您的根 url ,它看起来像https://<yourfirebase>.firebaseio.com

在我们的应用中启用 Firebase 需要对我们的应用添加两个小模块。

首先,我们需要在应用的www/index.html文件中包含 Firebase 脚本,如下所示:

 <script src='https://cdn.firebase.com/js/client/1.1.1/firebase.js'></script> <script src='https://cdn.firebase.com/libs/angularfire/0.8.0/angularfire.min.js'></script> <script src="js/app.js"></script>

接下来,我们需要通过将'firebase'添加到 AngularJS 'starter'模块的列表中来将 Firebase 模块添加到我们的应用程序中:

 angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'firebase'])

Firebase 现在已启用,就像任何其他 AngularJS 模块一样。

AngularFire 5 分钟教程将教您在控制器中创建数据引用。 不过,对于我们的演示应用程序,我决定将这些引用保存在一个单独的服务中(因为如果根 url 发生更改,这将更容易维护和更新)。 要创建此服务,请将以下内容添加到www/js/services.js

 .factory('fireBaseData', function($firebase) { var ref = new Firebase("https://luminous-fire-3429.firebaseio.com/"), refExpenses = new Firebase("https://luminous-fire-3429.firebaseio.com/expenses"), refRoomMates = new Firebase("https://luminous-fire-3429.firebaseio.com/room-mates"); return { ref: function() { return ref; }, refExpenses: function() { return refExpenses; }, refRoomMates: function() { return refRoomMates; } } });

上面的代码添加了三个参考网址。 一个用于根目录,两个用于我们命名为expensesroom-mates的集合。

将新集合添加到 Firebase 只需将其名称添加到根 url的末尾即可。 因此,要创建我们需要的expenses集合,我们只需要以下内容:

https://<yourfirebase>.firebaseio.com/expenses

这将创建expenses集合,然后我们可以开始向其中添加对象。

好的,现在我们可以挂钩来自 Firebase 的费用集合来替换我们之前创建的“虚拟”费用数组。 这是通过修改www/js/controllers.js中的DashCtrl来完成的,如下所示:

 .controller('DashCtrl', function($scope, fireBaseData, $firebase) { $scope.expenses = $firebase(fireBaseData.refExpenses()).$asArray(); $scope.addExpense = function(e) { $scope.expenses.$add({ by: < someemail > , label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function() { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })

需要对FriendsCtrl进行一组类似的更改。 我再次建议您尝试自己执行此操作,但如果您遇到问题,或者想验证您是否已正确执行此操作,您可以参考我在 GitHub 上的实现。

要验证它是否正常工作,在两个不同的客户端上运行应用程序时,添加新费用,并查看它是否显示在两个客户端的列表中。 如果它有效……呜呼! 您现在已成功将您的 Ionic 应用程序与 Firebase 连接起来!

您可以通过将设备连接到系统并运行ionic run androidionic emulate ios在不同设备上测试您的多平台应用程序。 有关测试您的应用程序的更多信息,请参阅 Ionic 文档。

Firebase 的帐户管理和安全性

尽管基本功能现在可以使用,但一个严重的问题是我们的应用程序目前完全不安全。 全世界都可以看到您的支出,无需任何权限或登录。 这显然需要解决。

Firebase 使用“规则”提供了一个强大而简单的身份验证框架。 使用 Firebase 的规则语言可以做很多事情。 (有关更多详细信息,请参阅 Firebase 安全文档。)

在我们的例子中,我们将编写一个非常简单的规则来阻止未经授权的用户访问我们的数据。 为此,请打开您的根 URL,单击左侧操作栏中的“安全和规则”,将下面的代码粘贴到您的规则中,然后单击“保存”。

 { "rules": { ".read": "auth != null", ".write": "auth != null" } }

如果您现在运行您的应用程序,您会注意到没有数据。 您甚至可以尝试使用浏览器工具检查您的请求,您应该会在控制台中看到一条消息,说明您无权查看数据。

创建用户帐户并启用登录

您可以通过让他们创建自己的电子邮件/密码组合或使用他们现有的任何 Google、Facebook、Twitter 或 Github 登录凭据来验证您的用户。 对于电子邮件/密码身份验证,Firebase 提供了用于更改、重置密码等的全套 API 方法。有关使用 Firebase 进行身份验证的更多信息,请参阅 Firebase 指南。

对于我们的演示应用,我们将通过 Firebase 界面创建两个用户帐户。 这可以通过转到您的 Firebase 根 URL 并执行以下操作来完成:

  1. 单击左侧操作栏上的登录和验证。
  2. 选中复选框以启用电子邮件和密码验证。
  3. 向下滚动以找到“添加新帐户表单”
  4. 使用“添加新用户”添加您的帐户。

在使用 Ionic 和 Firebase 开发多平台应用程序时,启用安全登录至关重要。

要为您的用户启用登录界面,首先将以下代码添加到www/templates/tab-account.html

 <ion-view title="Account"> <ion-content> <div class="list" ng-show="showLoginForm"> <label class="item item-input"> <span class="input-label">Email</span><input type="text" ng-model="em"/> </label> <label class="item item-input"> <span class="input-label">Password</span><input type="password" ng-model="pwd"/> </label> <button class="button button-block button-positive" ng-click="login(em, pwd)">Login</button> </div> <div class="card" ng-hide="showLoginForm"> <div class="item item-text-wrap">You are logged in as {{user.password.email}}</div> </div> <button class="button button-stable" ng-click="logout()" ng-hide="showLoginForm">Logout</button> </ion-content> </ion-view>

然后将以下内容添加到www/controller.js中的AccountCtrl

 .controller('AccountCtrl', function($scope, fireBaseData) { $scope.showLoginForm = false; //Checking if user is logged in $scope.user = fireBaseData.ref().getAuth(); if (!$scope.user) { $scope.showLoginForm = true; } //Login method $scope.login = function (em, pwd) { fireBaseData.ref().authWithPassword({ email : em, password : pwd },function(error, authData) { if (error === null) { console.log("User ID: " + authData.uid + ", Provider: " + authData.provider); $scope.user = fireBaseData.ref().getAuth(); $scope.showLoginForm = false; $scope.$apply(); } else { console.log("Error authenticating user:", error); } }); }; // Logout method $scope.logout = function () { fireBaseData.ref().unauth(); $scope.showLoginForm = true; }; });

从安全角度来看,需要注意的一件重要事情是Firebase 登录默认情况下是持久的。 因此,如果您希望用户每次启动应用程序时都需要登录,则需要相应地修改 Firebase 配置。 为此,只需在成功登录一次后,执行以下代码:

 var r = $firebase(fireBaseData.refRoomMates()).$asArray(); // NOTE: Substitute the email addresses of your two user accounts in the line below r.$add(["[email protected]","[email protected]"]);

您可以在成功登录后将其添加到帐户控制器中,或者在成功登录后放置一个断点并在控制台检查器中运行它。

基于用户的过滤

不过,多平台移动应用程序仍然缺少一项重要功能。 我们希望将您的费用与您室友的费用区分开来。 现在我们已经创建了两个帐户,我们只需要过滤视图上的数据。

我们首先需要修改www/js/controllers.js中的dashCtrl ,以便 (a) 将当前用户的数据放入 $scope 并 (b) 保存当前用户的任何额外费用:

 .controller('DashCtrl', function($scope, fireBaseData, $firebase) { $scope.expenses = $firebase(fireBaseData.refExpenses()).$asArray(); $scope.user = fireBaseData.ref().getAuth(); // ADD MESSAGE METHOD $scope.addExpense = function(e) { $scope.expenses.$add({ by: $scope.user.password.email, label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function () { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })

接下来我们需要在www/templates/tab-dash.html中添加一个过滤器来只显示当前用户的费用:

 <ion-item ng-repeat="expense in expenses|filter:user.password.email" type="item-text-wrap">

好的,主屏幕现在很完美。 用户只能查看和添加他或她自己的费用。

最后一步是在室友之间共享完整的费用清单。 为此,请更改www/templates/tab-friends.html以添加此过滤器:

 <ion-item ng-repeat="expense in expenses|filter:roomiesEmail" type="item-text-wrap">

然后修改www/controllers.js中的FriendsCtrl如下:

 .controller('FriendsCtrl', function($scope, fireBaseData, $firebase) { $scope.user = fireBaseData.ref().getAuth(); $scope.expenses = $firebase(fireBaseData.refExpenses()).$asArray(); $scope.roomies = $firebase(fireBaseData.refRoomMates()).$asArray(); $scope.roomies.$loaded().then(function(array) { //array = [[set1_rm1_email, set1_rm2_email], [set2_rm1_email, set2_rm2_email] ...] for (var i = 0; i < array.length; i++) { if (array[i][0] === $scope.user.password.email) { $scope.roomiesEmail = array[i][1]; } else if (array[i][1] === $scope.user.password.email) { $scope.roomiesEmail = array[i][0]; } } $scope.$apply(); // NOTE: For simplicity, this demo only supports the 2-roommate use case }); $scope.addExpense = function(e) { $scope.expenses.$add({ by: $scope.roomiesEmail, label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function () { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })

而已! 在您的设备和室友的设备上安装/更新应用程序,您应该已经准备就绪!

包起来

我们的简单示例仅开始触及使用 Ionic 和 Firebase 可以完成的任务以及完成的难易程度的皮毛。 它们确实是使用 JavaScript 和 HTML5 构建实时、多平台智能手机应用程序的强大组合。

相关: Angular 6 教程:具有新功能的新功能(包括 Firebase 后端的完整堆栈示例)