深入浅析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 相关文章推荐
仿校内登陆框,精美,给那些很厉害但是没有设计天才的程序员
Nov 24 Javascript
关于Jqzoom的使用心得 jquery放大镜效果插件
Apr 12 Javascript
JavaScript实现页面实时显示当前时间的简单实例
Jul 20 Javascript
判断某个字符在一个字符串中是否存在的js代码
Feb 28 Javascript
JQuery实现带排序功能的权限选择实例
May 18 Javascript
JS/Jquery判断对象为空的方法
Jun 11 Javascript
基于JavaScript实现右键菜单和拖拽功能
Nov 28 Javascript
jQuery插件zTree实现删除树子节点的方法示例
Mar 08 Javascript
VUE多层路由嵌套实现代码
May 15 Javascript
vue中实现先请求数据再渲染dom分享
Mar 17 Javascript
vue源码解析之事件机制原理
Apr 21 Javascript
layUI实现列表查询功能
Jul 27 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
PHP4实际应用经验篇(3)
2006/10/09 PHP
支持中文的php加密解密类代码
2011/11/27 PHP
php实现快速排序法函数代码
2012/08/27 PHP
完美解决thinkphp唯一索引重复时出错的问题
2017/03/31 PHP
激活 ActiveX 控件
2006/10/09 Javascript
一实用的实现table排序的Javascript类库
2007/09/12 Javascript
jquery之超简单的div显示和隐藏特效demo(分享)
2013/07/09 Javascript
用JavaScript实现对话框的教程
2015/06/04 Javascript
angular源码学习第一篇 setupModuleLoader方法
2016/10/20 Javascript
js实现登录框鼠标拖拽效果
2017/03/09 Javascript
微信小程序开发之实现自定义Toast弹框
2017/06/08 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
Vue.js结合Ueditor富文本编辑器的实例代码
2017/07/11 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
nodejs遍历文件夹下并操作HTML/CSS/JS/PNG/JPG的方法
2018/11/01 NodeJs
python实现文件分组复制到不同目录的例子
2014/06/04 Python
跟老齐学Python之类的细节
2014/10/13 Python
使用Python编写一个模仿CPU工作的程序
2015/04/16 Python
python学习之第三方包安装方法(两种方法)
2015/07/30 Python
python url 参数修改方法
2018/12/26 Python
opencv 形态学变换(开运算,闭运算,梯度运算)
2020/07/07 Python
python中upper是做什么用的
2020/07/20 Python
浅析Python的命名空间与作用域
2020/11/25 Python
Python结合百度语音识别实现实时翻译软件的实现
2021/01/18 Python
基于tensorflow __init__、build 和call的使用小结
2021/02/26 Python
英国最大的老式糖果店:A Quarter Of
2017/04/08 全球购物
韩国11街:11STREET
2018/03/27 全球购物
班主任个人工作反思
2014/04/28 职场文书
2014年最新版离婚协议书范本
2014/11/25 职场文书
助学感谢信范文
2015/01/21 职场文书
安全守法证明
2015/06/23 职场文书
Nginx 过滤静态资源文件的访问日志的实现
2021/03/31 Servers
Python数据类型最全知识总结
2021/05/31 Python
MySQL库表太大怎么办? 数据库分库分表项目实践
2022/04/11 MySQL
Golang获取List列表元素的四种方式
2022/04/20 Golang
MySQL的意向共享锁、意向排它锁和死锁
2022/07/15 MySQL