firebase创建数据库_创建Firebase供电的端到端离子应用程序

firebase创建数据库

自人类用石头开火以来,技术已经走了很长一段路。 曾经有一段时间,Internet旨在跨几台机器提供超文本文档。 但是今天,我们已经进入复杂的状态,您的心率由设备监控,然后传输到您的计算机。 如果心率不正常,则在冲刺结束时您甚至可能会看到一辆救护车在等待。

这些天我们几乎过着这种生活。 为了提供如此惊人的功能,我们需要拥有惊人的技术。 在本文中,我们将讨论两种此类前沿技术,即Ionic Framework和Firebase。

什么是离子框架?

Ionic是强大的AngularJS驱动的移动Web框架,使构建混合移动应用程序变得容易。 它不仅具有双向数据绑定的功能,而且还具有用于RESTful API的强大界面。 这使得Ionic非常适合开发应用程序并使它们在设备之间保持同步。

什么是Firebase?

有时候,调配一台机器来部署一个简单的网站将花费数周的时间。 然后,亚马逊来了。 您只需告诉Amazon您想要哪种系统,它就会为您提供服务器。 接下来,我们看到了Heroku的兴起,它提供了PaaS(平台即服务)来托管您的应用程序。 这使开发人员可以将更多精力放在应用程序上,而不必担心配置和部署应用程序。 最后,我们有了Firebase,它是由NoSQL数据存储驱动的自足的“服务器即服务”。 在Firebase中,您所需要做的就是定义一个数据集合,Firebase将为您提供将其作为RESTful API公开的信息。

清单清单申请

我写了一篇名为《 Ionic Restify MongoDB –端到端混合应用程序》的文章 ,其中介绍了如何使用Restify和MongoDB作为API服务器并使用Ionic作为混合客户端构建端到端混合应用程序。 在这篇文章中,我们将看到如何使用Firebase完全消除API服务器层。

我们将要构建的Bucketlist应用程序将具有一个身份验证层,允许用户注册和登录。 身份验证后,将为用户提供创建新存储桶项目的选项。

应用程序的主视图显示未完成项目的列表,而辅助视图显示已完成项目的列表。 用户可以选择将项目标记为完成或删除。

在我们开始构建应用程序之前,您应该:

应用架构

我们的应用程序将主要包括两层。 第一个是客户端( 在我们的示例中为Ionic App,但这可以是任何其他可以使用RESTful API的客户端 ),第二个是服务器( Firebase )。

应用架构

从上图可以看到,在客户端,我们有一个Angularfire层,该层与Firebase交互并充当Ionic应用程序的服务层。 正是这一层使Firebase和Ionic客户端之间的数据保持同步。

在Firebase端,我们将配置一个简单的登录名以处理身份验证。

我们的离子应用程序将具有五个关键控制器:

  1. 注册控制器
  2. 登录控制器
  3. 创建新的项目控制器
  4. 显示不完整的物品控制器
  5. 显示完成的项目控制器

除此之外,我们将提供两种方法来将项目标记为完成并删除该项目。

设计数据结构

Firebase是实时数据同步的理想选择,在该数据中,全球多个客户端几乎可以在同一时刻看到相同的数据。 我们的应用程序并非如此。 我们确实不是在寻找多设备同步。 我们需要的只是Firebase来为我们管理存储桶数据。

Firebase的出色之处在于它提供了现成的身份验证API。 我们需要做的就是启用它并包含客户端,Firebase将为我们处理其余的工作。

对于bucketlist集合,我们需要用户和bucketlist Item之间的关系,有点像外键。 这将使我们能够显示仅由用户创建的存储桶项目。

样表列表示例如下所示:

"BucketListCollection":
[{
  "item": "test",
  "isCompleted": false,
  "user": "test@bla.com",
  "created": 1400801853144,
  "updated": 1400801853144
}, {
  "item": "tes message",
  "isCompleted": false,
  "user": "test@bla.com",
  "created": 1401008504927,
  "updated": 1401008504927
}, {
  "item": "Just to check",
  "isCompleted": true,
  "user": "test@bla.com",
  "created": 1401008534451,
  "updated": 1401008534451
}, ....]

在上面的示例JSON中, user密钥保留已登录用户及其项目之间的链接。 因此,当我们获取数据时,我们将获取与登录用户匹配的记录。 这就是我们使用RESTful端点表示查询的方式:

https://bucketlist-app.firebaseio.com/bucketList/test@bla.com

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

不幸的是,没有简单的方法可以在Firebase中实现。

根据此Stack Overflow帖子 ,有以下三种方法:

  • 智能地使用位置名称和优先级。
  • 进行客户端查询。
  • 运行单独的服务器。

对于简单的API而言,这些方法有点过分。 然后,我偶然发现了这篇Stack Overflow帖子 ,其中提到了如何翻转数据结构以用户为中心而不是以功能为中心。 因此,我更改了应用程序的数据结构,如下所示。

"test@bla,com" : [{
  "item": "test",
  "isCompleted": false,
  "created": 1400801853144,
  "updated": 1400801853144
}, {
  "item": "tes message",
  "isCompleted": false,
  "created": 1401008504927,
  "updated": 1401008504927
}....]

"test2@bla,com" : [{
  "item": "test2",
  "isCompleted": false,
  "created": 14008012853144,
  "updated": 14008012853144
}, {
  "item": "tes message2",
  "isCompleted": false,
  "created": 14010028504927,
  "updated": 14010028504927
}....]

现在,每个用户都有他们自己的集合,而不是公用的bucketlist集合,这在我们的应用程序中更有意义。 因此,我们将使用此结构来管理数据。 我们的网址如下所示:

https://bucketlist-app.firebaseio.com/test@bla,com

注意:我不确定100%的庞大用户群是否会影响单个查询的整体响应时间( 更多用户=更多集合 )。

设置Firebase

关于前往的目的地,我们有个好主意。 我们的第一步是设置一个Firebase帐户,创建一个新的Firebase应用程序实例,并为其配置身份验证。

导航到Firebase.com并创建一个新帐户(如果您没有)。 接下来,导航到“ 帐户”页面并创建一个新应用。 提供所需的名称和URL。 创建应用程序后,单击应用程序名称以导航到数据和配置页面。 这是后端的鸟瞰图。 在继续之前,请随意浏览。

接下来,我们将为我们的应用程序设置身份验证。 单击页面左侧的“简单登录”选项卡,然后在主要内容区域中将看到可用的选项。 在“ 身份验证提供程序”部分下,单击“ 电子邮件和密码” ,然后选中启用”复选框。 这将为我们设置“简单登录”。

设置一个离子项目

接下来,我们将使用Ionic命令行界面(CLI)从空白模板中构建新的Ionic应用程序。 创建一个名为myIonicFireApp的新文件夹,然后在此处打开终端/提示。 首先,我们将安装Cordova和Ionic。 执行以下命令:

$ npm i -g cordova ionic

接下来,我们将搭建一个新的Ionic应用程序。 通常,我喜欢保持代码井井有条。 由于这是一个测试应用程序,并且我们将不使用任何版本控制来管理开发和生产,因此我们将创建两个文件夹myIonicFireApp/devmyIonicFireApp/prod 。 此步骤是可选步骤,完全是首选步骤。 接下来,将cd放入dev文件夹(如果已创建),然后运行以下命令:

$ ionic start bucketListApp blank

bucketListApp是应用程序的名称。 这将为我们搭建Ionic + PhoneGap模板。 设置完成后,首先要做的就是将config.xmlbucketListApp文件夹移动到www文件夹( PhoneGap构建要求 )。

接下来,在您喜欢的编辑器中打开config.xml并更新小部件ID,名称,描述和作者字段。 当通过Phonegap Build运行时,这些将成为您应用程序的元数据。 更新后的文件如下所示:

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.ionicfire.bucketlist" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
  <name>BucketList App</name>
  <description>An Awesome App</description>
  <author email="hi@bucketlist.com" href="http://bucketlist.com/">Arvind Ravulavaru</author>
  <content src="index.html" />
  <access origin="*" />
  <preference name="fullscreen" value="true" />
  <preference name="webviewbounce" value="false" />
  <preference name="UIWebViewBounce" value="false" />
  <preference name="DisallowOverscroll" value="true" />
  <!-- Don't store local date in an iCloud backup. Turn this to "cloud" to enable storage
         to be sent to iCloud. Note: enabling this could result in Apple rejecting your app.
  -->
  <preference name="BackupWebStorage" value="none" />
  <feature name="StatusBar">
    <param name="ios-package" value="CDVStatusBar" onload="true" />
  </feature>
</widget>

请参阅Mac和Windows上的PhoneGap 3 CLI设置,以完全了解和设置Windows和Mac上的PhoneGap。

要添加iOS平台支持(仅限Mac),请运行以下命令:

$ ionic platform add ios

要添加Android平台支持,请运行以下命令:

$ ionic platform add android

接下来,我们将通过运行以下内容来构建应用程序:

$ ionic platform build ios

要么

$ ionic platform build ios

接下来,要模拟该应用程序,执行:

$ ionic emulate ios

要么

$ ionic emulate android

您可以使用上述方法来测试您的代码。 但是,每次更改www文件夹中的代码时,都需要为相应平台构建代码。

鉴于我的懒惰,我永远不会那样做。 Ionic项目附带了Gulp支持。 让我们利用这一点。 返回终端,执行以下命令:

$ npm install

这将安装package.json中列出的所有依赖项。 接下来,使用以下命令安装gulp-connect

$ npm install gulp-connect --save

然后,打开gulfile.js,存在于根bucketListApp文件夹,并用下面的代码替换:

var gulp = require('gulp');
var gutil = require('gulp-util');
var bower = require('bower');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var sh = require('shelljs');
var connect = require('gulp-connect');

var paths = {
  sass: ['./scss/**/*.scss'],
  www : ['www/**/*.*']
};

gulp.task('default', ['sass']);
gulp.task('serve', ['connect', 'watch']);

gulp.task('sass', function(done) {
  gulp.src('./scss/ionic.app.scss')
    .pipe(sass())
    .pipe(gulp.dest('./www/css/'))
    .pipe(minifyCss({
      keepSpecialComments: 0
    }))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(gulp.dest('./www/css/'))
    .on('end', done);
});

gulp.task('reload', function () {
  return gulp.src(['www/index.html'])
    .pipe(connect.reload());
});

gulp.task('watch', function() {
  // Uncomment below line if you wish to work wit SASS
  //gulp.watch(paths.sass, ['sass']);

  gulp.watch([paths.www], ['reload']);
});

gulp.task('install', ['git-check'], function() {
  return bower.commands.install()
    .on('log', function(data) {
      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
    });
});

gulp.task('git-check', function(done) {
  if (!sh.which('git')) {
    console.log(
      '  ' + gutil.colors.red('Git is not installed.'),
      '\n  Git, the version control system, is required to download Ionic.',
      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
    );
    process.exit(1);
  }
  done();
});

gulp.task('connect', function() {
  connect.server({
    root: 'www',
    port: '1881',
    livereload: true
  });
});

回到终端,运行:

$ gulp serve

这将启动服务器。 现在,您需要做的就是打开http://localhost:1881并观察!

请注意,在开发过程中cordova.js将为404。 而且,由于我们添加了实时重新加载支持,因此您所要做的就是进行更改并切换到浏览器以查看更改。

注意:如果您要使用通讯录或相机之类的本机插件构建应用程序,则此方法将行不通! 您需要将应用程序部署到设备上进行测试。

我们的离子应用程序设置完成。 让我们开始构建实际的应用程序。

离子与火力

我们要做的第一件事是打开www / index.html并添加所需的Firebase,AngularFire和Firebase简单登录JavaScript参考。

<script src="https://cdn.firebase.com/v0/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/0.5.0/angularfire.min.js"></script>
<script src="https://cdn.firebase.com/v0/firebase-simple-login.js"></script>

它们指向CDN,但是您也可以下载文件并将其本地存储。 接下来,将body标签上的ng-app指令值从starterbucketList 。 这将是我们的模块名称。 最后,我们将添加“后退”按钮支持。 将以下代码添加到页面正文中:

<ion-nav-bar class="bar-stable nav-title-slide-ios7">
  <ion-nav-back-button class="button-icon icon ion-chevron-left">
    Back
  </ion-nav-back-button>
</ion-nav-bar>

完整的www / index.html如下所示:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>
    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
      <link href="css/ionic.app.css" rel="stylesheet">
    -->
    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script src="https://cdn.firebase.com/v0/firebase.js"></script> <!-- firebase -->
    <script src="https://cdn.firebase.com/libs/angularfire/0.5.0/angularfire.min.js"></script> <!-- angularfire -->
    <script src="https://cdn.firebase.com/v0/firebase-simple-login.js"></script> <!-- firebase-simple-login -->
    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>
    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
  </head>
  <body ng-app="bucketList" animation="slide-left-right-ios7">
    <ion-nav-bar class="bar-stable nav-title-slide-ios7">
      <ion-nav-back-button class="button-icon icon ion-chevron-left">
        Back
      </ion-nav-back-button>
    </ion-nav-bar>
    <ion-nav-view></ion-nav-view>
  </body>
</html>

注意,我们已经添加了对controllers.js的引用。 我们将尽快解决。 如果返回浏览器并检查开发人员控制台,您将看到几个404和一个Uncaught object错误。 Uncaught object错误是因为,我们已在index.html中更新了ng-app指令,但未更新www / js / app.js中ng-app指令。 您可以取消gulp任务,因为我们将进行很多更改。 一切完成后,我们可以重新启动服务器。

在您喜欢的编辑器中打开www / js / app.js。 首先,让我们更新模块名称。 然后,我们将添加几个依赖项。 使用以下命令更新现有的模块声明:

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

主要依赖项是ionic ,next firebase ,最后是控制器。

为了开发我们的应用程序,我们将使用两对离子标签组件。 第一组标签将用于显示“登录和注册”屏幕,第二组标签将用于显示不完整的存储桶列表项和完整的存储桶列表项屏幕。

我们将把选项卡包装在另一个抽象选项卡中以获得更多控制。 这将使我们的总路线数达到6。 在run方法内部,我们将几个变量和方法注入$rootScope变量。 这将包括Firebase实例URL, checkSessionlogout和用于更好UX的加载程序。 最终的app.js将是

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

.run(function($ionicPlatform, $rootScope, $firebaseAuth, $firebase, $window, $ionicLoading) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      StatusBar.styleDefault();
    }

    $rootScope.userEmail = null;
    $rootScope.baseUrl = 'https://bucketlist-app.firebaseio.com/';
    var authRef = new Firebase($rootScope.baseUrl);
    $rootScope.auth = $firebaseAuth(authRef);

    $rootScope.show = function(text) {
      $rootScope.loading = $ionicLoading.show({
        content: text ? text : 'Loading..',
        animation: 'fade-in',
        showBackdrop: true,
        maxWidth: 200,
        showDelay: 0
      });
    };

    $rootScope.hide = function() {
      $ionicLoading.hide();
    };

    $rootScope.notify = function(text) {
      $rootScope.show(text);
      $window.setTimeout(function() {
        $rootScope.hide();
      }, 1999);
    };

    $rootScope.logout = function() {
      $rootScope.auth.$logout();
      $rootScope.checkSession();
    };

    $rootScope.checkSession = function() {
      var auth = new FirebaseSimpleLogin(authRef, function(error, user) {
        if (error) {
          // no action yet.. redirect to default route
          $rootScope.userEmail = null;
          $window.location.href = '#/auth/signin';
        } else if (user) {
          // user authenticated with Firebase
          $rootScope.userEmail = user.email;
          $window.location.href = ('#/bucket/list');
        } else {
          // user is logged out
          $rootScope.userEmail = null;
          $window.location.href = '#/auth/signin';
        }
      });
    }
  });
})

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('auth', {
      url: "/auth",
      abstract: true,
      templateUrl: "templates/auth.html"
    })
    .state('auth.signin', {
      url: '/signin',
      views: {
        'auth-signin': {
          templateUrl: 'templates/auth-signin.html',
          controller: 'SignInCtrl'
        }
      }
    })
    .state('auth.signup', {
      url: '/signup',
      views: {
        'auth-signup': {
          templateUrl: 'templates/auth-signup.html',
          controller: 'SignUpCtrl'
        }
      }
    })
    .state('bucket', {
      url: "/bucket",
      abstract: true,
      templateUrl: "templates/bucket.html"
    })
    .state('bucket.list', {
      url: '/list',
      views: {
        'bucket-list': {
          templateUrl: 'templates/bucket-list.html',
          controller: 'myListCtrl'
        }
      }
    })
    .state('bucket.completed', {
      url: '/completed',
      views: {
        'bucket-completed': {
          templateUrl: 'templates/bucket-completed.html',
          controller: 'completedCtrl'
        }
      }
    })
    $urlRouterProvider.otherwise('/auth/signin');
});

请注意,我们使用以下代码初始化Firebase Auth服务:

$rootScope.baseUrl = 'https://bucketlist-app.firebaseio.com/';
var authRef = new Firebase($rootScope.baseUrl);
$rootScope.auth = $firebaseAuth(authRef);

不要忘记用Firebase实例替换baseURL

现在,让我们构建controllers.js 。 在www/js创建一个新文件,并将其命名为controllers.js 。 顾名思义,该文件将包含所有控制器。 接下来,创建一个名为templates的新文件夹。 我们将逐步填充每个模板。

首先,我们有Signup控制器。 让我们首先创建所需的模板。 在templates文件夹中创建一个名为auth.html的新文件。 这将是“登录”和“注册”选项卡的抽象选项卡。 用以下代码填充它:

<ion-tabs class="tabs-icon-top">
  <ion-tab title="Sign In" icon-on="ion-ios7-locked"
    icon-off="ion-ios7-locked-outline" href="#/auth/signin">
    <ion-nav-view name="auth-signin"></ion-nav-view>
  </ion-tab>
  <ion-tab title="Sign Up" icon-on="ion-ios7-personadd"
    icon-off="ion-ios7-personadd-outline" href="#/auth/signup">
    <ion-nav-view name="auth-signup"></ion-nav-view>
  </ion-tab>
</ion-tabs>

接下来,让我们添加注册模板。 在templates文件夹中创建一个名为auth-signup.html的新文件,并添加以下代码:

<ion-header-bar class="bar-positive">
  <h1 class="title">Sign Up</h1>
</ion-header-bar>
<ion-content class="has-header padding">
  <div class="list">
    <label class="item item-input">
      <span class="input-label">Email</span>
      <input type="text" ng-model="user.email">
    </label>
    <label class="item item-input">
      <span class="input-label">Password</span>
      <input type="password" ng-model="user.password">
    </label>
    <label class="item item-input">
      <button class="button button-block button-positive" ng-click="createUser()">
        Sign Up
      </button>
    </label>
  </div>
</ion-content>

当用户单击提交时,我们将调用createuser() 。 控制器如下所示:

angular.module('bucketList.controllers', [])
  .controller('SignUpCtrl', [
    '$scope', '$rootScope', '$firebaseAuth', '$window',
    function ($scope, $rootScope, $firebaseAuth, $window) {
      $scope.user = {
        email: "",
        password: ""
      };
      $scope.createUser = function () {
        var email = this.user.email;
        var password = this.user.password;

        if (!email || !password) {
          $rootScope.notify("Please enter valid credentials");
          return false;
        }

        $rootScope.show('Please wait.. Registering');
        $rootScope.auth.$createUser(email, password, function (error, user) {
          if (!error) {
            $rootScope.hide();
            $rootScope.userEmail = user.email;
            $window.location.href = ('#/bucket/list');
          }
          else {
            $rootScope.hide();
            if (error.code == 'INVALID_EMAIL') {
              $rootScope.notify('Invalid Email Address');
            }
            else if (error.code == 'EMAIL_TAKEN') {
              $rootScope.notify('Email Address already taken');
            }
            else {
              $rootScope.notify('Oops something went wrong. Please try again later');
            }
          }
        });
      }
    }
  ])

注意事项:

  1. app.js中定义了$rootScope.show()$rootScope.hide()$rootScope.notify()来显示加载叠加层。
  2. $rootScope.auth.$createUser()负责与Firebase进行交互并创建新用户。
  3. 请注意Firebase返回的各种错误消息。 您可以在此处找到整个列表。
  4. 成功注册后,我们会将用户重定向到我们的主视图。

接下来是Signin控制器。 在templates文件夹中创建一个名为auth-signin.html的新文件,并添加以下标记:

<ion-header-bar class="bar-positive">
  <h1 class="title">Sign In</h1>
</ion-header-bar>
<ion-content class="has-header padding">
  <div class="list">
    <label class="item item-input">
      <span class="input-label">Email</span>
      <input type="text" ng-model="user.email">
    </label>
    <label class="item item-input">
      <span class="input-label">Password</span>
      <input type="password" ng-model="user.password">
    </label>
    <label class="item item-input">
      <button class="button button-block button-positive" ng-click="validateUser()">Sign In</button>
    </label>
  </div>
</ion-content>

当用户单击提交时,我们称为validateUser() 。 控制器将是( 从上方继续 ):

.controller('SignInCtrl', [
  '$scope', '$rootScope', '$firebaseAuth', '$window',
  function ($scope, $rootScope, $firebaseAuth, $window) {
     // check session
     $rootScope.checkSession();
     $scope.user = {
        email: "",
        password: ""
     };
     $scope.validateUser = function () {
        $rootScope.show('Please wait.. Authenticating');
        var email = this.user.email;
        var password = this.user.password;
        if (!email || !password) {
           $rootScope.notify("Please enter valid credentials");
           return false;
        }
        $rootScope.auth.$login('password', {
           email: email,
           password: password
        })
        .then(function (user) {
          $rootScope.hide();
          $rootScope.userEmail = user.email;
          $window.location.href = ('#/bucket/list');
        }, function (error) {
          $rootScope.hide();
          if (error.code == 'INVALID_EMAIL') {
            $rootScope.notify('Invalid Email Address');
          }
          else if (error.code == 'INVALID_PASSWORD') {
            $rootScope.notify('Invalid Password');
          }
          else if (error.code == 'INVALID_USER') {
            $rootScope.notify('Invalid User');
          }
          else {
            $rootScope.notify('Oops something went wrong. Please try again later');
          }
        });
     }
  }
])

注意事项:

  1. $rootScope.auth.$login()负责Firebase身份验证。
  2. $rootScope.auth.$login()返回一个promise,在请求完成后将被解决。
  3. 成功认证后,我们将重定向到主视图。

接下来,让我们构建应用程序的主视图。 在templates文件夹中创建一个名为bucket.html的新文件,并添加以下代码:

<ion-tabs class="tabs-icon-top">
  <ion-tab title="My List" icon-on="ion-ios7-browsers"
    icon-off="ion-ios7-browsers-outline" href="#/bucket/list">
    <ion-nav-view name="bucket-list"></ion-nav-view>
  </ion-tab>
  <ion-tab title="Completed" icon-on="ion-ios7-checkmark"
    icon-off="ion-ios7-checkmark-outline" href="#/bucket/completed">
    <ion-nav-view name="bucket-completed"></ion-nav-view>
  </ion-tab>
</ion-tabs>

这是抽象视图,其中包含我们的存储清单完整和不完整视图。 接下来,在templates文件夹中创建一个名为bucket-list.html的新文件,并添加以下代码:

<ion-header-bar class="bar-positive">
  <button class="button button-clear" ng-click="newTask()">New</button>
  <h1 class="title">My Bucket List</h1>
  <button class="button button-clear" ng-click="logout()">Logout</button>
</ion-header-bar>
<ion-content class="has-header padding" has-tabs="true" on-refresh="onRefresh()">
  <div class="card" ng-repeat="item in list" id="{{item.key}}" >
    <div class="item item-text-wrap">
      <span>{{ item.item }}</span>
      <br/>  <br/>
      <p class="actions padding">
        <i class="ion-checkmark-circled icon-actions margin" ng-click="markCompleted('{{item.key}}')"></i>
        <i class="ion-trash-b icon-actions margin" ng-click="deleteItem('{{item.key}}')"></i>
      </p>
    </div>
  </div>
  <div class="card" >
    <div class="item item-text-wrap" ng-show="noData">
      <span>
      No Items in your bucket List. Click  <a href="javascript:" ng-click="newTask()">Here</a> and create one
      </span>
    </div>
  </div>
</ion-content>

注意事项:

  1. 我们在标题中添加了一个“ 新建”按钮。 这将打开一个弹出窗口,用户可以在其中输入项目描述并创建它。
  2. 视图的主体将渲染一张卡片 ,其中将显示项目说明以及“ 删除”和“ 标记为已完成”图标。

控制器如下所示:

.controller('myListCtrl', function($rootScope, $scope, $window, $ionicModal, $firebase) {
  $rootScope.show("Please wait... Processing");
  $scope.list = [];
  var bucketListRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail));
  bucketListRef.on('value', function(snapshot) {
    var data = snapshot.val();

    $scope.list = [];

    for (var key in data) {
      if (data.hasOwnProperty(key)) {
        if (data[key].isCompleted == false) {
          data[key].key = key;
          $scope.list.push(data[key]);
        }
      }
    }

    if ($scope.list.length == 0) {
      $scope.noData = true;
    } else {
      $scope.noData = false;
    }
    $rootScope.hide();
  });

  $ionicModal.fromTemplateUrl('templates/newItem.html', function(modal) {
    $scope.newTemplate = modal;
  });

  $scope.newTask = function() {
    $scope.newTemplate.show();
  };

  $scope.markCompleted = function(key) {
    $rootScope.show("Please wait... Updating List");
    var itemRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail) + '/' + key);
    itemRef.update({
      isCompleted: true
    }, function(error) {
      if (error) {
        $rootScope.hide();
        $rootScope.notify('Oops! something went wrong. Try again later');
      } else {
        $rootScope.hide();
        $rootScope.notify('Successfully updated');
      }
    });
  };

  $scope.deleteItem = function(key) {
    $rootScope.show("Please wait... Deleting from List");
    var itemRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail));
    bucketListRef.child(key).remove(function(error) {
      if (error) {
        $rootScope.hide();
        $rootScope.notify('Oops! something went wrong. Try again later');
      } else {
        $rootScope.hide();
        $rootScope.notify('Successfully deleted');
      }
    });
  };
})

注意事项:

  • Designing the data structure部分中所述,我们将基于登录用户Designing the data structure Firebase参考。
var bucketListRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail));

我们正在创建一个转义用户的电子邮件地址后命名的集合。 您可以添加escapeEmailAddress()controllers.js的底部定义。

function escapeEmailAddress(email) {
  if (!email) return false
  // Replace '.' (not allowed in a Firebase key) with ','
  email = email.toLowerCase();
  email = email.replace(/\./g, ',');
  return email.trim();
}
  • 接下来,我们将使用此动态引用通过on监听器为value事件提取所有列表项。 每当集合发生更改时( Firebase的最佳组成部分之一 ),就会触发此操作。
  • 我们检查项目是否未完成data[key].isCompleted == false ,然后将其添加到要显示的项目列表中。
  • 我们还注册了newTask() ,它将打开“ Create New项目”弹出窗口。
  • $scope.markCompleted()$scope.deleteItem() ,与Firebase API交互以将isCompleted值更新为true并分别从集合中删除一条数据。

接下来,我们将添加newCtrl ,负责创建新的控制器。 在templates文件夹中创建一个名为newItem.html的新文件,并添加以下代码:

<div class="modal slide-in-up" ng-controller="newCtrl">
  <header class="bar bar-header bar-secondary">
    <button class="button button-clear button-primary" ng-click="close()">Cancel</button>
    <h1 class="title">New Item</h1>
    <button class="button button-positive" ng-click="createNew()">Done</button>
  </header>
  <ion-content class="padding has-header">
    <input type="text" placeholder="I need to do..." ng-model="data.item">
  </ion-content>
</div>

单击Done ,我们调用createUser() 。 在controller.js中添加以下代码:

.controller('newCtrl', function($rootScope, $scope, $window, $firebase) {
  $scope.data = {
    item: ""
  };

  $scope.close = function() {
    $scope.modal.hide();
  };

  $scope.createNew = function() {
    var item = this.data.item;

    if (!item) return;

    $scope.modal.hide();
    $rootScope.show();
    $rootScope.show("Please wait... Creating new");

    var form = {
      item: item,
      isCompleted: false,
      created: Date.now(),
      updated: Date.now()
    };

    var bucketListRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail));
    $firebase(bucketListRef).$add(form);
    $rootScope.hide();
  };
})

注意事项:

  • 我们构建一个表单对象,该表单对象将由所有基本数据组成,以创建一个新的存储桶项目。
  • 我们将生成与用户集合的新连接,然后使用$firebase(bucketListRef).$add(form); 我们将数据插入到集合中。
  • 插入数据后,Firebase会触发value事件,这将刷新我们的存储桶项目视图。

最后,让我们添加控制器以显示所有已完成的存储桶列表项。 在templates文件夹中创建一个名为bucket-completed.html的新文件,并添加以下代码:

<ion-header-bar class="bar-positive">
  <h1 class="title">Completed Items</h1>
  <button class="button button-clear" ng-click="logout()">Logout</button>
</ion-header-bar>
<ion-content class="has-header padding" has-tabs="true" on-refresh="onRefresh()">
  <div class="card" ng-repeat="item in list" >
    <div class="item item-text-wrap">
      <span>{{ item.item }}</span>
      <br/>  <br/>
      <p class="actions padding">
        <i class="ion-trash-b icon-actions margin" ng-click="deleteItem('{{item.key}}')"></i>
      </p>
    </div>
  </div>
  <div class="card" >
    <div class="item item-text-wrap" ng-show="noData || incomplete">
      <span ng-show="incomplete">
      You can have not completed any of your Bucket List items yet. Try harder!!
      </span>
      <span ng-show="noData">
      No Items in your bucket List.
      </span>
    </div>
  </div>
</ion-content>

除了Create New项目和Mark Item Incomplete之外,此控制器与不完整的存储区列表控制器相似。 如果需要,您也可以在此处添加它们。 控制器如下所示:

.controller('completedCtrl', function($rootScope, $scope, $window, $firebase) {
  $rootScope.show("Please wait... Processing");
  $scope.list = [];

  var bucketListRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail));
  bucketListRef.on('value', function(snapshot) {
    $scope.list = [];
    var data = snapshot.val();

    for (var key in data) {
      if (data.hasOwnProperty(key)) {
        if (data[key].isCompleted == true) {
          data[key].key = key;
          $scope.list.push(data[key]);
        }
      }
    }
    if ($scope.list.length == 0) {
      $scope.noData = true;
    } else {
      $scope.noData = false;
    }

    $rootScope.hide();
  });

  $scope.deleteItem = function(key) {
    $rootScope.show("Please wait... Deleting from List");
    var itemRef = new Firebase($rootScope.baseUrl + escapeEmailAddress($rootScope.userEmail));
    bucketListRef.child(key).remove(function(error) {
      if (error) {
        $rootScope.hide();
        $rootScope.notify('Oops! something went wrong. Try again later');
      } else {
        $rootScope.hide();
        $rootScope.notify('Successfully deleted');
      }
    });
  };
});

最后,让我们添加一些CSS。 在www/css文件夹中打开style.css并添加以下代码:

.margin {
  margin-left: 9px;
  margin-right: 9px;
}
.icon-actions {
  font-size: 23px;
}
.checkbox {
  vertical-align: middle;
}
.actions {
  float: right;
}
.item-text-wrap {
  overflow: auto;
}
.ion-checkmark-circled.icon-actions.margin{
  margin-right: 35px;
}

大功告成! 让我们运行该应用程序,看看它的外观。 在终端中,运行:

gulp serve

这将启动服务器。 接下来,浏览至http://localhost:1881 ,您应该会看到登录视图。 单击注册并注册一个帐户。 注册成功后,您将被重定向到存储桶列表视图。 玩转全新的Firebase驱动的Ionic应用程序

注意:您也可以转到Firebase应用程序帐户,并在那里查看数据结构。

发出PhoneGap构建

我们已经成功构建了一个可以在浏览器中正常运行的应用。 让我们构建一个本机安装程序,看看该应用程序如何在实际设备上运行。

注意:如果您不熟悉PhoneGap,我建议您先阅读PhoneGap快速入门,然后再继续。

步骤1:首先,将myIonicFireApp/dev/bucketListApp/www文件夹及其内容myIonicFireApp/prodmyIonicFireApp/prod 。 这就是我们发布PhoneGap版本所需的全部。

步骤2:创建一个名为IonicFirePGInstaller的新GitHub IonicFirePGInstaller

步骤3: cd进入myIonicFireApp/prod文件夹( 不在www文件夹中 )并运行以下命令:

$ git init
$ git add -A
$ git commit -am "Initial Commit"
$ git remote add origin git@github.com:sitepoint/IonicFirePGInstaller.git

确保更新存储库路径以指向您创建的路径。 最后,检查代码:

$ git push origin master

这会将代码推送到GitHub。

步骤4:导航到PhoneGap Build并登录。

步骤5:单击+ New App然后在open-source下提交GitHub repo URL( https而非ssh )。 现在,PhoneGap服务将转到GitHub并获取存储库。 加载回购文件后,您将看到“ Ready to Build按钮。 单击它以发出PhoneGap版本。

构建完成后,您可以下载设备的安装程序并测试该应用程序。

结论

到此结束有关使用Firebase和Ionic框架构建混合应用程序的文章。 希望您对如何建立自己的一个想法很了解。

  • 您可以找到我们在GitHub上开发的代码库。
  • 您还可以找到可提交到GitHub上的 PhoneGap构建的www文件夹。
  • 您可以在此处下载应用程序安装程序。

谢谢阅读!

翻译自: https://www.sitepoint.com/creating-firebase-powered-end-end-ionic-application/

firebase创建数据库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值