如果您想了解在AngularJS框架中处理数据建模的方式解析和angularjsmodule的知识,那么本篇文章将是您的不二之选。我们将深入剖析在AngularJS框架中处理数据建模的方式解析的各个方
如果您想了解在AngularJS框架中处理数据建模的方式解析和angularjs module的知识,那么本篇文章将是您的不二之选。我们将深入剖析在AngularJS框架中处理数据建模的方式解析的各个方面,并为您解答angularjs module的疑在这篇文章中,我们将为您介绍在AngularJS框架中处理数据建模的方式解析的相关知识,同时也会详细的解释angularjs module的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- 在AngularJS框架中处理数据建模的方式解析(angularjs module)
- angularjs – Firebase / AngularFire中的数据建模最佳实践
- angularjs – 你在Angular中存储/创建模型的位置?
- angularjs – 在angularUI路由器中处理斜杠
- AngularJS 数据建模
在AngularJS框架中处理数据建模的方式解析(angularjs module)
我们知道,AngularJS并没有自带立等可用的数据建模方案。而是以相当抽象的方式,让我们在controller中使用JSON数据作为模型。但是随着时间的推移和项目的成长,我意识到这种建模的方式不再能满足我们项目的需求。在这篇文章中我会介绍在我的AngularJS应用中处理数据建模的方式。
为Controller定义模型
让我们从一个简单的例子开始。我想要显示一个书本(book)的页面。下面是控制器(Controller):
BookController
这个控制器创建了一个书本的模型,我们可以在后面的模板中(templage)中使用它。
template for displaying a book
Name:
Author:
假如我们需要从后台的api获取书本的数据,我们需要使用$http: BookController with $http
$http.get('ourserver/books/' + bookId).success(function(bookData) {
$scope.book = bookData;
});
}]);
注意到这里的bookData仍然是一个JSON对象。接下来我们想要使用这些数据做一些事情。比如,更新书本信息,删除书本,甚至其他的一些不涉及到后台的操作,比如根据请求的图片大小生成一个书本图片的url,或者判断书本是否有效。这些方法都可以被定义在控制器中。
BookController with several book actions
$scope.book = bookData;
});
$scope.deleteBook = function() {
$http.delete('ourserver/books/' + bookId);
};
$scope.updateBook = function() {
$http.put('ourserver/books/' + bookId,$scope.book);
};
$scope.getBookImageUrl = function(width,height) {
return 'our/image/service/' + bookId + '/width/height';
};
$scope.isAvailable = function() {
if (!$scope.book.stores || $scope.book.stores.length === 0) {
return false;
}
return $scope.book.stores.some(function(store) {
return store.quantity > 0;
});
};
}]);
然后在我们的模板中:
template for displaying a complete book
Name:
Author:
Is Available: <span ng-bind="isAvailable() ? 'Yes' : 'No' ">
<button ng-click="deleteBook()">Delete
<button ng-click="updateBook()">Update
在controllers之间共享Model
如果书本的结构和方法只和一个控制器有关,那我们现在的工作已经可以应付。但是随着应用的增长,会有其他的控制器也需要和书本打交道。那些控制器很多时候也需要获取书本,更新它,删除它,或者获得它的图片url以及看它是否有效。因此,我们需要在控制器之间共享这些书本的行为。我们需要使用一个返回书本行为的factory来实现这个目的。在动手写一个factory之前,我想在这里先提一下,我们创建一个factory来返回带有这些book辅助方法的对象,但我更倾向于使用prototype来构造一个Book类,我觉得这是更正确的选择:Book model service
};
Book.prototype = {
setData: function(bookData) {
angular.extend(this,bookData);
},load: function(id) {
var scope = this;
$http.get('ourserver/books/' + bookId).success(function(bookData) {
scope.setData(bookData);
});
},delete: function() {
$http.delete('ourserver/books/' + bookId);
},update: function() {
$http.put('ourserver/books/' + bookId,this);
},getImageUrl: function(width,height) {
return 'our/image/service/' + this.book.id + '/width/height';
},isAvailable: function() {
if (!this.book.stores || this.book.stores.length === 0) {
return false;
}
return this.book.stores.some(function(store) {
return store.quantity > 0;
});
}
};
return Book;
}]);
这种方式下,书本相关的所有行为都被封装在Book服务内。现在,我们在BookController中来使用这个亮眼的Book服务。
BookController that uses Book model
正如你看到的,控制器变得非常简单。它创建一个Book实例,指派给scope,并从后台加载。当书本被加载成功时,它的属性会被改变,模板也随着被更新。记住其他的控制器想要使用书本功能,只要简单地注入Book服务即可。此外,我们还要改变template使用book的方法。
template that uses book instance
Name:
Author:
Is Available: <span ng-bind="book.isAvailable() ? 'Yes' : 'No' ">
<button ng-click="book.delete()">Delete
<button ng-click="book.update()">Update
angularjs – Firebase / AngularFire中的数据建模最佳实践
例如,我的应用程序有很多用户,每个用户创建许多帖子.
User { firstName: String,lastname: String,userName: String } Post { title: String,content: String,date: Date,writtenBy: [User object?] }
我应该如何在Firebase中构建这两个对象,以便帖子属于用户,但是无论用户如何都可以查询所有帖子,并且可以在不中断其他对象的数据和/或关系的情况下编辑用户和帖子对象?
我应该如何通过firebase创建新的“关系”对象:
sync.$set({userA: { firstname: "Billy",lastName: "Bob",userName: "BillyBob",Posts: { // ..... } } });
谢谢!
解决方法
设计数据结构的方法仍然很多,这取决于您要执行哪些查询.如果其中一个查询能够显示所有消息(我相信一些最新消息将是最常见的用例),但同时您希望能够显示每个用户的消息而不是一个可能的消息数据结构可能如下所示:
User { userId(assigned by Firebase automatically) { firstName: String,userName: String } } Post { User { userId(matching userId in the User object) { postId(assigned by Firebase for every new post automatically) { title: String,writtenBy: String,userName or userId (this is not really needed,but may keep it for easier data access) } } } }
然后,您可以更改任何用户数据,而不会触发帖子中的数据更改事件,例如您的示例中(如果您有大量邮件,这将非常繁重).
您可以独立于用户获取所有消息:
var postListRef = new Firebase(URL); var lastPostQuery = postListRef.child("Post").limit(500);
你也可以使用startAt()和endAt()问题https://www.firebase.com/docs/web/api/query/limit.html
作为一个缺点 – 如果你只需要显示消息,你必须在for循环中解压缩每条消息,但我希望你也会显示用户信息,所以它应该没问题.
如果您只想收听一条用户消息,那么它非常简单快捷:
var postListRef = new Firebase(URL); var lastPostQuery = postListRef.child("Post/User").child(userId);
Angular / AngularFire对这种数据结构有很大的支持.
angularjs – 你在Angular中存储/创建模型的位置?
customer.js:
function customer(){ this.firstName; this.lastName; } customer.prototype.getFullName = function(){ return this.firstName + ' ' + this.lastName; }
我还看到了工厂的使用:
customerFactory.js:
app.factory("customer",function(){ return function(){ this.firstName; this.lastName; this.getFullName = function(){ return this.firstName + ' ' + this.lastName; }; }; });
所以我的问题是,你在哪里存储模型以及为什么?这个人比其他人有更多优势吗?
解决方法
为什么?因为这是Angular应用程序的构建方式.这样做允许您将它们注入您的控制器,指令等.如果您希望您的模型是Angular不可知的,那很好.它适合“端口和适配器”架构.稍后将它们作为工厂公开.将您的Angular-agnostic代码分离到一个单独的库中,然后将它们暴露出来以便以后注入:
app.factory("Customer",function(){ return Models.Customer; }); app.factory("Order",function(){ return Models.Order; });
另外,请注意我喜欢用大写字母命名我的类对象…这是一个约定我真的想表明它是一个实例化的“类”.
angularjs – 在angularUI路由器中处理斜杠
我有一个可能导致用户实际输入网址的应用程序。在这种情况下,不难相信用户可能会输入尾部斜线。例如,
www.example.com/users/2 and www.example.com/edit/company/123
应该是一样的
www.example.com/users/2/ and www.example.com/edit/company/123/
这只需要在客户端处理URL路由。我没有兴趣在资源/ API调用中处理尾部斜杠。我只想在浏览器中处理拖尾的兴趣。
所以我研究并发现网上没有多少答案。他们中的大多数引导我到角ui路由器的FAQ部分。
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions
在这里,他们告诉我们写一个规则,这是我想要做的,但它似乎没有工作,或者也许我做错了。
这是我添加了我的代码的plunkr。
http://plnkr.co/edit/fD9q7L?p=preview
我把它添加到我的配置,其余的代码是基本的东西。
$urlRouterProvider.rule(function($injector,$location) { //if last charcter is a slash,return the same url without the slash if($location.$$url[length-1] === '/') { return $location.$$url.substr(0,$location.$$url.length - 2); } else { //if the last char is not a trailing slash,do nothing return $location.$$url; } });
基本上,我想使可选的尾部斜线,即地址栏的存在或不存在对加载的状态没有影响。
这是更新的规则定义:
$urlRouterProvider.rule(function($injector,$location) { var path = $location.path(); var hasTrailingSlash = path[path.length-1] === '/'; if(hasTrailingSlash) { //if last charcter is a slash,return the same url without the slash var newPath = path.substr(0,path.length - 1); return newPath; } });
这些链接现在可以正常工作:
<ul> <li><a ui-sref="route1">Route 1</a></li> <li><a ui-sref="route2">Route 2</a></li> <li><a href="#/route1/">#/route1/</a></li> <li><a href="#/route2/">#/route2/</a></li> <li><a href="#/route1" >#/route1</a></li> <li><a href="#/route2" >#/route2</a></li> </ul>
魔术可以这样定义:如果有变化,请返回更改值…否则不做任何事情… see example
AngularJS 数据建模
本文由 伯乐在线 - 陈 鑫伟 翻译自 Naor Yehudaey 。欢迎加入技术翻译小组。转载请参见文章末尾处的要求。我们知道,AngularJS并没有自带立等可用的数据建模方案。而是以相当抽象的方式,让我们在controller中使用JSON数据作为模 型。但是随着时间的推移和项目的成长,我意识到这种建模的方式不再能满足我们项目的需求。在这篇文章中我会介绍在我的AngularJS应用中处理数据建 模的方式。
为Controller定义模型
让我们从一个简单的例子开始。我想要显示一个书本(book)的页面。下面是控制器(Controller):
BookController
app.controller(''BookController'', [''$scope'', function($scope) {
$scope.book = {
id: 1,
name: ''Harry Potter'',
author: ''J. K. Rowling'',
stores: [
{ id: 1, name: ''Barnes & Noble'', quantity: 3},
{ id: 2, name: ''Waterstones'', quantity: 2},
{ id: 3, name: ''Book Depository'', quantity: 5}
]
};
}]);
这个控制器创建了一个书本的模型,我们可以在后面的模板中(templage)中使用它。
<div ng-controller="BookController">
Id: <span ng-bind="book.id"></span>
Name:<input type="text" ng-model="book.name" />
Author: <input type="text" ng-model="book.author" />
</div>
BookController with $http
app.controller(''BookController'', [''$scope'', ''$http'', function($scope, $http) {
var bookId = 1;
$http.get(''ourserver/books/'' + bookId).success(function(bookData) {
$scope.book = bookData;
});
}]);
注意到这里的bookData仍然是一个JSON对象。接下来我们想要使用这些数据做一些事情。比如,更新书本信息,删除书本,甚至其他的一些不涉及到后台的操作,比如根据请求的图片大小生成一个书本图片的url,或者判断书本是否有效。这些方法都可以被定义在控制器中。
BookController with several book actions
app.controller(''BookController'', [''$scope'', ''$http'', function($scope, $http) {
var bookId = 1;
$http.get(''ourserver/books/'' + bookId).success(function(bookData) {
$scope.book = bookData;
});
$scope.deleteBook = function() {
$http.delete(''ourserver/books/'' + bookId);
};
$scope.updateBook = function() {
$http.put(''ourserver/books/'' + bookId, $scope.book);
};
$scope.getBookImageUrl = function(width, height) {
return ''our/image/service/'' + bookId + ''/width/height'';
};
$scope.isAvailable = function() {
if (!$scope.book.stores || $scope.book.stores.length === 0) {
return false;
}
return $scope.book.stores.some(function(store) {
return store.quantity > 0;
});
};
}]);
然后在我们的模板中:
template for displaying a complete book
<div ng-controller="BookController">
<div ng-></div>
Id: <span ng-bind="book.id"></span>
Name:<input type="text" ng-model="book.name" />
Author: <input type="text" ng-model="book.author" />
Is Available: <span ng-bind="isAvailable() ? ''Yes'' : ''No'' "></span>
<button ng-click="deleteBook()">Delete</button>
<button ng-click="updateBook()">Update</button>
</div>
如果书本的结构和方法只和一个控制器有关,那我们现在的工作已经可以应付。但是随着应用的增长,会有其他的控制器也需要和书本打交道。那些控制器很 多时候也需要获取书本,更新它,删除它,或者获得它的图片url以及看它是否有效。因此,我们需要在控制器之间共享这些书本的行为。我们需要使用一个返回 书本行为的factory来实现这个目的。在动手写一个factory之前,我想在这里先提一下,我们创建一个factory来返回带有这些book辅助 方法的对象,但我更倾向于使用prototype来构造一个Book类,我觉得这是更正确的选择:
Book model service
app.factory(''Book'', [''$http'', function($http) {
function Book(bookData) {
if (bookData) {
this.setData(bookData):
}
// Some other initializations related to book
};
Book.prototype = {
setData: function(bookData) {
angular.extend(this, bookData);
},
load: function(id) {
var scope = this;
$http.get(''ourserver/books/'' + bookId).success(function(bookData) {
scope.setData(bookData);
});
},
delete: function() {
$http.delete(''ourserver/books/'' + bookId);
},
update: function() {
$http.put(''ourserver/books/'' + bookId, this);
},
getImageUrl: function(width, height) {
return ''our/image/service/'' + this.book.id + ''/width/height'';
},
isAvailable: function() {
if (!this.book.stores || this.book.stores.length === 0) {
return false;
}
return this.book.stores.some(function(store) {
return store.quantity > 0;
});
}
};
return Book;
}]);
这种方式下,书本相关的所有行为都被封装在Book服务内。现在,我们在BookController中来使用这个亮眼的Book服务。
BookController that uses Book model
app.controller(''BookController'', [''$scope'', ''Book'', function($scope, Book) {
$scope.book = new Book();
$scope.book.load(1);
}]);
正如你看到的,控制器变得非常简单。它创建一个Book实例,指派给scope,并从后台加载。当书本被加载成功时,它的属性会被改变,模板也随着被更 新。记住其他的控制器想要使用书本功能,只要简单地注入Book服务即可。此外,我们还要改变template使用book的方法。
template that uses book instance
<div ng-controller="BookController">
<div ng-></div>
Id: <span ng-bind="book.id"></span>
Name:<input type="text" ng-model="book.name" />
Author: <input type="text" ng-model="book.author" />
Is Available: <span ng-bind="book.isAvailable() ? ''Yes'' : ''No'' "></span>
<button ng-click="book.delete()">Delete</button>
<button ng-click="book.update()">Update</button>
</div>
在多个控制器中使用相同的书本模型
我们定义了一个书本模型,并且在多个控制器中使用了它。在使用了这种建模架构之后你会注意到有一个严重的问题。到目前为止,我们假设多个控制器对书本进行操作,但如果有两个控制器同时处理同一本书会是什么情况呢?
假设我们页面的一块区域我们所有书本的名称,另一块区域可以更新某一本书。对应这两块区域,我们有两个不同的控制器。第一个加载书本列表,第二个加 载特定的一本书。我们的用户在第二块区域中修改了书本的名称并且点击“更新”按钮。更新操作成功后,书本的名称会被改变。但是在书本列表中,这个用户始终 看到的是修改之前的名称!真实的情况是我们对同一本书创建了两个不同的书本实例——一个在书本列表中使用,而另一个在修改书本时使用。当用户修改书本名称 的时候,它实际上只修改了后一个实例中的属性。然而书本列表中的书本实例并未得到改变。
解决这个问题的办法是在所有的控制器中使用相同的书本实例。在这种方式下,书本列表和书本修改的页面和控制器都持有相同的书本实例,一旦这个实例发 生变化,就会被立刻反映到所有的视图中。那么按这种方式行动起来,我们需要创建一个booksManager服务(我们没有大写开头的b字母,是因为这是 一个对象而不是一个类)来管理所有的书本实例池,并且富足返回这些书本实例。如果被请求的书本实例不在实例池中,这个服务会创建它。如果已经在池中,那么 就直接返回它。请牢记,所有的加载书本的方法最终都会被定义在booksManager服务中,因为它是唯一的提供书本实例的组件。
booksManager service
app.factory(''booksManager'', [''$http'', ''$q'', ''Book'', function($http, $q, Book) {
var booksManager = {
_pool: {},
_retrieveInstance: function(bookId, bookData) {
var instance = this._pool[bookId];
if (instance) {
instance.setData(bookData);
} else {
instance = new Book(bookData);
this._pool[bookId] = instance;
}
return instance;
},
_search: function(bookId) {
return this._pool[bookId];
},
_load: function(bookId, deferred) {
var scope = this;
$http.get(''ourserver/books/'' + bookId)
.success(function(bookData) {
var book = scope._retrieveInstance(bookData.id, bookData);
deferred.resolve(book);
})
.error(function() {
deferred.reject();
});
},
/* Public Methods */
/* Use this function in order to get a book instance by it''s id */
getBook: function(bookId) {
var deferred = $q.defer();
var book = this._search(bookId);
if (book) {
deferred.resolve(book);
} else {
this._load(bookId, deferred);
}
return deferred.promise;
},
/* Use this function in order to get instances of all the books */
loadAllBooks: function() {
var deferred = $q.defer();
var scope = this;
$http.get(''ourserver/books)
.success(function(booksArray) {
var books = [];
booksArray.forEach(function(bookData) {
var book = scope._retrieveInstance(bookData.id, bookData);
books.push(book);
});
deferred.resolve(books);
})
.error(function() {
deferred.reject();
});
return deferred.promise;
},
/* This function is useful when we got somehow the book data and we wish to store it or update the pool and get a book instance in return */
setBook: function(bookData) {
var scope = this;
var book = this._search(bookData.id);
if (book) {
book.setData(bookData);
} else {
book = scope._retrieveInstance(bookData);
}
return book;
},
};
return booksManager;
}]);
下面是我们的EditableBookController和BooksListController两个控制器的代码:
EditableBookController and BooksListController that uses booksManager
app.factory(''Book'', [''$http'', function($http) {
function Book(bookData) {
if (bookData) {
this.setData(bookData):
}
// Some other initializations related to book
};
Book.prototype = {
setData: function(bookData) {
angular.extend(this, bookData);
},
delete: function() {
$http.delete(''ourserver/books/'' + bookId);
},
update: function() {
$http.put(''ourserver/books/'' + bookId, this);
},
getImageUrl: function(width, height) {
return ''our/image/service/'' + this.book.id + ''/width/height'';
},
isAvailable: function() {
if (!this.book.stores || this.book.stores.length === 0) {
return false;
}
return this.book.stores.some(function(store) {
return store.quantity > 0;
});
}
};
return Book;
}]);
需要注意的是,模块(template)中还是保持原来使用book实例的方式。现在应用中只持有一个id为1的book实例,它发生的所有改变都会被反映到使用它的各个页面上。
总结
在这片文章中,我建议了AngularJS中建模数据的一种架构。首先,我展示了AngularJS默认的数据模型绑定,然后讲了如何封装模型的方 法和操作从而可以在不同的控制其中重用它们,最后我解释了如何管理模型实例从而使得所有的改变都能被反映到应用中各个相关的视图上。
希望这篇文章能在如何实现数据建模上给你一些启示。
原文链接: Naor Yehudaey 翻译: 伯乐在线 - 陈 鑫伟译文链接: http://blog.jobbole.com/54817/
[ 转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]
关于在AngularJS框架中处理数据建模的方式解析和angularjs module的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于angularjs – Firebase / AngularFire中的数据建模最佳实践、angularjs – 你在Angular中存储/创建模型的位置?、angularjs – 在angularUI路由器中处理斜杠、AngularJS 数据建模的相关知识,请在本站寻找。
本文标签: