firebase创建数据库
如您所知, FireBase充当应用程序的实时后端。 好吧,我们都知道这有多棒。 但是,您知道更棒的吗? 它是AngularJS + FireBase。 FireBase具有一个正式发布的绑定,称为AngularFire ,它将FireBase的所有乐趣和乐趣带给了AngularJS。 作为AngularJS开发人员,我们非常喜欢数据绑定,甚至我们梦dream以求! 借助AngularFire,我们可以利用三向数据绑定(而不是AngularJS中的传统两向数据绑定)来创建一些很棒的东西。 本教程将概述使用AngularFire创建简单的实时应用时的三种方式绑定。 本文假定读者已经了解FireBase,并已在AngularJS中进行了一些先前的开发。
什么是三向数据绑定
在AngularJS中,由于两种方式的数据绑定,我们的范围模型和视图保持同步。 但是,如果您引入AngularFire,从而将FireBase用作后端,则可以通过三种方式绑定功能来增强自己的能力。 您基本上可以将模型数据绑定到FireBase位置,以便每当您更改模型时,这些更改就会自动推送到FireBase。 同样,只要特定FireBase位置的数据发生更改,您的本地范围模型也会被更新。 并且,由于我们的视图和范围模型已经同步,因此创建了三种方式的数据绑定。 明显的好处是,它使您可以创建很酷的实时应用程序,在这些应用程序中数据经常更改,并且这些更改会广播给所有连接的用户。 这一切都不需要任何大的努力。 如果您要构建聊天应用程序,多人游戏应用程序或广播系统,则可以利用此功能。
入门
为了演示三向绑定的概念,让我们创建一个示例应用程序。 我们的应用程序将是一个实时广播系统,用户可以在其中实时广播自己输入的内容。 对于每个用户,将有两个选择:
- 开始广播
- 观看广播
要开始广播,用户需要提供广播的名称。 用户键入名称并单击“开始”后,便可以开始广播。 要查看广播,他们需要从下拉菜单中选择一个广播。
基本架构
首先,我们需要了解如何存储广播数据。 首先,登录到FireBase并创建一个新的FireBase存储。 我创建了一个名为angularfiredemo
,因此我们将使用URL https://angularfiredemo.firebaseio.com
来存储数据。 请注意,每个FireBase位置均由URL表示,我们可以进行多次广播来处理将要使用我们系统的许多用户。 让我们将所有广播存储在https://angularfiredemo.firebaseio.com/broadcasts
。 每个广播都有两个部分:名称和内容,由键/值对表示。 广播数据样本如下图所示。
要观看广播,用户将需要在FireBase中选择由密钥表示的特定广播名称。 我们的下一步是围绕这些关键点构建AngularJS应用。
那些对最终产品感兴趣的人可以在Plunker上查看演示。 要获得实时体验,请并排打开浏览器的两个实例。 首先,给您的广播起一个名字,开始它,然后开始写作。 在第二种情况下,从下拉菜单中选择刚开始的广播。 现在您可以实时观看广播。
构建应用
首先,我们需要以下脚本:
-
AngularJS
:主要的AngularJS脚本。 -
FireBase
:用于启用FireBase支持的脚本。 -
AngularFire
:AngularJS的FireBase绑定。 -
Angular Route
:用于AngularJS中的路由支持。 -
Angular Sanitize
:清理来自FireBase的传入数据。
为了快速设计布局,我们将使用Bootstrap CSS。
第1步
第一步是创建我们的主应用程序模块,如下所示:
angular.module('firebaseDemo', ['firebase', 'ngSanitize', 'ngRoute']);
angular.module('firebaseDemo').constant('FIREBASE_URL','https://angularfiredemo.firebaseio.com/broadcasts');
我们的主要模块依赖于其他三个模块: firebase
, ngSanitize
和ngRoute
。 所有的AngularFire功能封装到它自己的模块中, firebase
。 ngSanitize
和ngRoute
分别用于ngRoute
数据和路由支持。 我们还定义了一个常量FIREBASE_URL
,它代表存储所有广播的位置。
第2步
现在,让我们创建一个从FireBase检索广播的工厂。
angular.module('firebaseDemo').factory('broadcastFactory', function($firebase,FIREBASE_URL) {
return {
getBroadcast: function(key) {
return $firebase(new Firebase(FIREBASE_URL + '/' + key));
},
getAllBroadcasts: function() {
return $firebase(new Firebase(FIREBASE_URL));
}
};
});
我们的工厂broadcastFactory
声明了对FIREBASE_URL
的依赖关系,该依赖关系表示我们广播的位置。 我们的工厂还依赖于名为$firebase
firebase的AngularFire服务。 它接受FireBase
对象,并返回与远程FireBase位置保持同步的特殊对象。 它具有像$add()
, $set()
, $child()
等函数来处理数据。 每当对此本地对象进行更新时,所做的更改就会被推送到远程FireBase位置。
工厂具有两个功能:
-
getBroadcast(key)
:这返回一个代表广播的对象。 该对象具有一个称为$value
的属性,该属性表示广播的内容。 我们使用此对象创建三向绑定,以便无论用户键入什么内容,都始终与远程FireBase位置保持同步。 -
getBroadcasts()
:此函数返回一个对象,该对象具有所有广播作为其属性。 我们将这些数据呈现给用户,以便他们可以选择要观看的广播。
第三步
下一步是在index.html
创建我们的主视图:
<!DOCTYPE html>
<html ng-app="firebaseDemo">
<head>
<meta charset="utf-8" />
<title>AngularFire Demo</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
<script src="https://code.angularjs.org/1.2.16/angular-sanitize.js" data-semver="1.2.16"></script>
<script src="https://code.angularjs.org/1.2.16/angular-route.js" data-semver="1.2.16"></script>
<script src="https://cdn.firebase.com/js/client/1.0.6/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/0.7.1/angularfire.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div class="container"> <br/>
<div class="row">
<div class="col-xs-5 col-xs-offset-1 text-right">
<a class="btn btn-lg btn-primary" href="/write">Write Something</a>
</div>
<div class="col-xs-5 text-left">
<a class="btn btn-lg btn-success" href="/view">View a Broadcast</a>
</div>
</div>
<div ng-view></div>
</div>
</body>
</html>
主视图有两个链接:
-
Write Something
:加载新的AngularJS路由,使用户可以开始广播。 -
View a Broadcast
:加载允许用户查看广播的AngularJS路由。
您还可以看到ng-view
指令,将在其中加载不同的路由。 我们所有的AngularJS代码都存在于app.js
。
注意 :任何认真的AngularJS应用都应考虑按层或功能对代码进行模块化。 对于这个简单的应用程序,我将所有AngularJS组件(如controllers
和directives
放在单个文件app.js
。 但这当然不是大规模AngularJS应用的方法。
第4步
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
接下来,创建两个不同的视图:一个用于广播,另一个用于查看。 我们还将使用$routeProvider
配置路由。 以下代码来自views/write.html
。
<hr/>
<div class="row">
<div class="col-xs-4 col-xs-offset-3">
<input type="text" class="form-control input-lg" ng-model="broadcastName" placeholder="Type your broadcast name here" />
</div>
<div class="col-xs-5">
<button class="btn btn-lg btn-success" ng-click="startBroadcast()" ng-disabled='isButtonEnabled()'>Start</button>
</div>
</div>
<h1 class="text-center">Write Something. . .</h1>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<div id="editor" demo-editor model="broadcast" class="well">
</div>
</div>
</div>
不用担心<div id="editor" demo-editor></div>
。 demoEditor
是一个自定义指令,将在下面显示。
与该视图关联的相应控制器为:
angular.module('firebaseDemo').controller('BroadcastController', function($scope, broadcastFactory) {
$scope.isEditable = false;
$scope.broadcastName = '';
$scope.isButtonEnabled = function() {
return ($scope.broadcastName === 'undefined') || ($scope.broadcastName.length < 1);
};
$scope.startBroadcast = function() {
$scope.isEditable = true;
$scope.broadcastFromFireBase = broadcastFactory.getBroadcast($scope.broadcastName);
$scope.broadcastFromFireBase.$set('');
$scope.broadcastFromFireBase.$bind($scope, 'broadcast');
};
});
我们的控制器有两个依赖项, $scope
和broadcastFactory
。 isEditable
范围模型用于指示我们的编辑器是否处于活动状态。 当用户单击视图中的“开始”按钮时,编辑器将处于活动状态并接受输入。 我们的视图还包含绑定到范围模型broadcastName
的文本字段。 在开始广播之前,我们要求用户为广播命名。 广播内容将根据此密钥存储在我们的FireBase中。
isButtonEnabled()
函数用于跟踪广播名称是否为空。 如果是这样,那么我们将禁用“开始”按钮。 此功能与“开始”按钮上附加的ng-disabled
指令一起使用。
startBroadcast()
函数用于启动广播。 由于ng-click
指令,单击“开始”按钮时将调用此函数。 在此函数内部,我们将isEditable
模型设置为true
,从而激活编辑器。 接下来,我们调用broadcastFactory.getBroadcast()
函数,并将broadcastName
作为键。 然后,我们使用$set()
在此位置设置一个空字符串。 这充当初始广播内容。 请注意,此操作在https://angularfiredemo.firebaseio.com/broadcasts
下创建一个新子级。 该子项的名称与$scope.broadcastName
的值相同。 因此,新广播的存储位置为https://angularfiredemo.firebaseio.com/broadcasts/<broadcastName>
。 请注意,此位置的初始内容将是一个空字符串。
最后,我们将执行最关键的操作,这将创建三向绑定。 操作$scope.broadcastFromFireBase.$bind($scope, 'broadcast');
做这个。 因此,远程FireBase位置与我们的本地范围模型broadcast
保持同步。 此本地模型也绑定到我们的编辑器。 结果,每当用户在编辑器中键入内容时, broadcast
模型就会更新。 并且,由于三向绑定,远程FireBase内容也将使用此新广播内容进行更新。
现在,让我们转到存在于views/view.html
下一个视图。
<h1 class="text-center">Live Broadcast</h1>
<div class="row">
<div class="col-xs-4 col-xs-offset-4">
<select ng-model="broadcastToView" ng-change="broadcastSelected()" class="form-control" ng-options="k as k for (k, v) in broadcasts">
<option value="">{{dropdownMessage}}</option>
</select>
</div>
</div>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<div id="editor" class="well" ng-bind-html="broadcast.$value">
</div>
</div>
</div>
相应的控制器代码如下所示。
angular.module('firebaseDemo').controller('BroadcastViewerController', function($scope, broadcastFactory) {
$scope.dropdownMessage = 'Retrieving Broadcasts...';
$scope.broadcasts = broadcastFactory.getAllBroadcasts();
$scope.broadcastSelected = function() {
$scope.broadcast = broadcastFactory.getBroadcast($scope.broadcastToView);
}
$scope.broadcasts.$on('loaded', function() {
$scope.dropdownMessage = 'Select a broadcast';
});
});
路由加载后,我们通过调用broadcastFactory.getAllBroadcasts()
获得所有广播。 请记住,这是一个包含所有子级作为属性的对象。 属性名称是广播名称,而它们的值表示广播内容。 这些广播名称会在下拉列表中显示给用户,以便他们可以选择要查看的广播。
当下拉值由于选择而更改时,将调用函数broadcastSelected()
。 此函数使用broadcastFactory.getBroadcast()
获得特定的广播对象。 该对象具有一个称为$value
的属性,该属性表示实际内容。 最后,我们通过ng-bind-html
将此值绑定到div
,以便用户可以实时查看广播。 ng-bind-html
是因为FireBase位置也可能具有HTML内容。 由于此指令,我们包括了ngSanitize
模块(以净化数据),否则该指令将引发异常。
另请注意,加载视图时,FireBase数据将不会立即同步。 几秒钟后, $scope.broadcasts
将具有实际值。 因此,在数据从服务器同步之前,最好表明我们正在检索下拉数据。 这就是为什么我有模型$scope.dropdownMessage
用作下拉菜单中的第一个<option>
的原因。 当实际从服务器同步数据时,将触发loaded
事件,并且我们将dropdownMessage
值更改为Select a broadcast
。
第5步
我们还有一个自定义指令demoEditor
,它可以将div
转换为可编辑的div
以便用户可以在其中键入。 我知道我们可以只使用一个简单的textarea
,但是如果您想让用户能够编写HTML,该怎么办? 也许某种所见即所得的编辑器? 在这种情况下,我们需要一个div
,用户可以在其中键入。 这是我们的指令定义:
angular.module('firebaseDemo').directive('demoEditor', function(broadcastFactory) {
return {
restrict: 'AE',
link: function(scope, elem, attrs) {
scope.$watch('isEditable', function(newValue) {
elem.attr('contenteditable', newValue);
});
elem.on('keyup keydown', function() {
scope.$apply(function() {
scope[attrs.model] = elem.html().trim();
});
});
}
};
});
该指令非常简单。 编辑器div
最初是不可编辑的,并且当用户单击“开始”时变为可编辑。 由于这是一个div
元素,因此无法附加ng-model
将其内容同步到模型。 因此,我们附加了一个keyup keydown
侦听器,以使范围模型与此div
内容保持同步。 scope
模型名称(我们希望保持更新)作为属性传递给指令。 万一您错过了它,该指令将在如下视图中使用:
<div id="editor" demo-editor model="broadcast" class="well"></div>
model
属性指定要保持同步的scope
模型。 另请注意,此伪指令不会创建新的作用域。 它使用父范围。
第6步
让我们配置路线,并享受酷炫的三通绑定!
angular.module('firebaseDemo').config(function($routeProvider, $locationProvider) {
$routeProvider.when('/write', {
controller: 'BroadcastController',
templateUrl: '/views/write.html'
}).when('/view', {
controller: 'BroadcastViewerController',
templateUrl: '/views/view.html'
}).otherwise({
redirectTo: '/write'
});
$locationProvider.html5Mode(true);
});
结论
我希望您喜欢使用AngularJS和FireBase进行试验。 AngularJS与FireBase结合使用时,可用于创建实时同步的出色应用。 我鼓励您阅读AngularFire文档以了解有关API方法的更多信息。 有一个美好的实时 !
完整的源代码可以从GitHub下载。
翻译自: https://www.sitepoint.com/creating-three-way-data-binding-firebase-angularjs/
firebase创建数据库