深入浅析AngularJS和DataModel


Posted in Javascript onFebruary 16, 2016

AngularJS 简介

AngularJS 是一个 JavaScript 框架。它可通过 <script> 标签添加到 HTML 页面。

AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑定数据到 HTML。

什么是 AngularJS?

AngularJS 使得开发现代的单一页面应用程序(SPAs:Single Page Applications)变得更加容易。

AngularJS 把应用程序数据绑定到 HTML 元素。

AngularJS 可以克隆和重复 HTML 元素。

AngularJS 可以隐藏和显示 HTML 元素。

AngularJS 可以在 HTML 元素"背后"添加代码。

AngularJS 支持输入验证。

通常,在AngularJS中使用JSON作为存储数据的模型。我们可能这样在controller中写model:

app.controller('BookController',['$scope',function($scope){
$scope.book = {
id:1,
name:'',
author:'',
stores:[
{id:1, name:'', quantity:2},
{id:2, name:'', quantity:2},
...
]
};
}])

在视图中也许这样用到这个model:

<div ng-controller="BookController">
<span ng-bind="book.id"></span>
<input type="text" ng-model="book.name"/>
<input type="text" ng-model="book.author"/>
</div>

当我们需要从服务端获取数据的时候,可能这样写:

app.controller('BookController',['$scope', '$http', function($scope, $http){
var bookId = 1;
$http.get('api/books'+bookId).success(function(bookData){
$scope.book = bookData;
})
$scope.deleteBook = function(){
$http.delete('api/books/' + bookId);
}
$scope.updateBook = function(){
$http.put('api/books/'+bookId, $scope.book);
}
$scope.getBookImageUrl = function(width, height){
return 'our/iamge/service' +bookId + '/width/height';
}
$scope.isAvailable = function(){
if(!$scope.book.stores || $scope.book.stores.length === 0){
return false;
}
reutrn $scope.book.stores.some(function(store){
return store.quantity > 0;
})
}
}])

在视图中可能这样使用:

<div ng-controller="BookController">
<div ng-style="{backgroundImage: 'url('+getBookImageUrl(100,100)+')'}"></div>
<span ng-bind="book.id"></span?
<input type="text" ng-model="book.name"/>
<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>

以上,JSON格式的model只能在BookController中使用,如何在其他controller中也可以使用呢?
--通过factory方式

app.factory('Book', ['$http', function($http){
function Book(bookData){
if(bookData){
this.setData(bookData);
}
}
Book.prototype = {
setData: function(bookData){
angular.extend(this, bookData);
},
load: function(id){
var scope = this;
$http.get('api/books/' + bookId).success(function(bookData){
scope.setData(bookData);
})
},
delete: function(bookId){
$http.delete('api/books/' + bookId);
},
update: function(bookId){
$http.put('api/books/' + bookId, this);
},
getImageUrl: function(width, height){
return 'our/image/service/' + this.book.id + '/' + width + '/' + height;
},
isAvailable: funciton(){
if(!this.book.stores || this.book.stores.length === 0) {
return false;
} 
return this.book.stores.some(function(store){
return store.quantity > 0;
})
}
}
return Book;
}])

以上,通过factory的方式创建了类似Book的一个Data Model,现在可以注入到controller中去了。

app.controller('BookController', ['$scope', 'Book', function($scope, Book){
$scope.book = new Book();
$scope.book.load(1);
}])

在视图中也会有相应的变化。

<div ng-controller="BookController">
<div ng-style="{backgroundImage: 'url(' + book.getImageUrl(100, 100) + ')'}"></div>
<span ng-bind="book.id"></span>
<input type="text" ng-model="book.name"/>
<input type="text" ng-model="book.author"/>
is abailble: <span ng-bind="book.isAvailabe() ? 'Yes' : 'No'"></span>
<button ng-click="book.delete()">Delete</button>
<button ng-click="book.update()">Update</button>
</div>

以上,多个controller可以使用同一个有关book的Data Model了,如果多个controller处理同一个有关book的Data Model呢?

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;
},
_seach: function(bookId){
reutrn this_.pool[bookId];
},
_load: function(bookId, deferred){
var scope = this;
$http.get('api/books/' + bookId)
.success(funciton(bookData){
var book = scope._retrieveInstance(bookData.id, bookData);
deferred.resolve(book);
})
.error(function(){
deferred.reject();
})
},
getBook: function(bookId){
var deferred = $q.defer();
var book = this._search(bookId);
if(book){
deferred.resove(book);
} else {
this._load(bookId, deferred);
}
return deferred.promise;
},
loadAllBooks: function(){
var deferred = $q.defer();
var scope = this;
$http.get('api/books')
.success(function(booksArray){
var books = [];
booksArray.forEach(function(bookData){
var book = scope.l_retrieveInstance(bookData.id, bookData);
books.push(book);
});
deferred.resolve(books);
})
.error(function(){
deferred.reject();
});
return deferred.promise;
},
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;
}])

Book服务去掉load方法。

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;
}]);

现在,多个controller可以使用同一个booksManager服务。

app.controller('EditableBookController',['$scope', 'booksManager', function($scope, booksManager){
booksManager.getBook(1).then(function(book){
$scope.book = book;
})
}])
.controller('BooksListController',['$scope', 'booksManager', function($scope, booksManager){
booksManager.loadAllBooks().then(function(books){
$scope.books = books;
})
}])
Javascript 相关文章推荐
innerHTML 和 getElementsByName 在IE下面的bug 的解决
Apr 09 Javascript
Extjs4中的分页应用结合前后台
Dec 13 Javascript
jQuery获取节点和子节点文本的方法
Jul 22 Javascript
window.location.href的用法(动态输出跳转)
Aug 09 Javascript
深入理解javascript作用域和闭包
Sep 23 Javascript
浅谈javascript语法和定时函数
May 03 Javascript
jQuery实现模仿微博下拉滚动条加载数据效果
Dec 25 Javascript
JavaScript SweetAlert插件实现超酷消息警告框
Jan 28 Javascript
使用BootStrap实现悬浮窗口的效果
Dec 13 Javascript
使用veloticy-ui生成文字动画效果
Feb 08 Javascript
js 判断当前时间是否处于某个一个时间段内
Sep 19 Javascript
React-redux实现小案例(todolist)的过程
Sep 29 Javascript
Javascript中的Prototype到底是什么
Feb 16 #Javascript
剖析Node.js异步编程中的回调与代码设计模式
Feb 16 #Javascript
使用Node.js处理前端代码文件的编码问题
Feb 16 #Javascript
让图片跳跃起来  javascript图片轮播特效
Feb 16 #Javascript
Node.js本地文件操作之文件拷贝与目录遍历的方法
Feb 16 #Javascript
详解Node.js包的工程目录与NPM包管理器的使用
Feb 16 #Javascript
javascript每日必学之运算符
Feb 16 #Javascript
You might like
建立动态的WML站点(二)
2006/10/09 PHP
PHP令牌 Token改进版
2008/07/18 PHP
使用PHP 5.0创建图形的巧妙方法
2010/10/12 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
PHP生成不重复标识符的方法
2014/11/21 PHP
php实现比较两个字符串日期大小的方法
2015/05/12 PHP
php遍历替换目录下文件指定内容的方法
2016/11/10 PHP
php实现留言板功能(会话控制)
2017/05/23 PHP
PHP实现下载远程图片保存到本地的方法
2017/06/19 PHP
PHP的RSA加密解密方法以及开发接口使用
2018/02/11 PHP
把html页面的部分内容保存成新的html文件的jquery代码
2009/11/12 Javascript
javascript 触发HTML元素绑定的函数
2010/09/11 Javascript
javascript中的对象创建 实例附注释
2011/02/08 Javascript
js时间日期和毫秒的相互转换
2013/02/22 Javascript
jQuery事件之键盘事件(ctrl+Enter回车键提交表单等)
2014/05/11 Javascript
Node.js实现简单聊天服务器
2014/06/20 Javascript
Jquery 实现弹出层插件
2015/01/28 Javascript
javascript-解决mongoose数据查询的异步操作
2016/12/22 Javascript
微信小程序 简单教程实例详解
2017/01/13 Javascript
利用ES6语法重构React组件详解
2017/03/02 Javascript
vue+mockjs模拟数据实现前后端分离开发的实例代码
2017/08/08 Javascript
引入JavaScript时alert弹出框显示中文乱码问题
2017/09/16 Javascript
vue实现多个元素或多个组件之间动画效果
2018/09/25 Javascript
[00:31]DOTA2上海特级锦标赛 Fnatic战队宣传片
2016/03/04 DOTA
Python删除指定目录下过期文件的2个脚本分享
2014/04/10 Python
跟老齐学Python之重回函数
2014/10/10 Python
Python内置函数—vars的具体使用方法
2017/12/04 Python
python3+PyQt5 自定义窗口部件--使用窗口部件样式表的方法
2019/06/26 Python
通过代码实例解析Pytest运行流程
2020/08/20 Python
介绍一下Java的安全机制
2012/06/28 面试题
市场营销方案范文
2014/03/11 职场文书
2014领导班子“四风问题”对照检查材料思想汇报(执法局)
2014/09/21 职场文书
安全承诺书
2015/01/19 职场文书
nginx内存池源码解析
2021/11/20 Servers
Android studio 简单计算器的编写
2022/05/20 Java/Android
利用Python实现模拟登录知乎
2022/05/25 Python