深入浅析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 相关文章推荐
Javascript alert消息换行的方法
Aug 07 Javascript
javascript如何使用bind指定接收者
May 04 Javascript
简介JavaScript中strike()方法的使用
Jun 08 Javascript
jquery移动端TAB触屏切换实现效果
Dec 22 Javascript
关于JavaScript限制字数的输入框的那些事
Aug 14 Javascript
DropDownList实现可输入可选择(两种版本可选)
Dec 07 Javascript
微信小程序 五星评价功能的实现
Mar 09 Javascript
微信小程序开发之实现自定义Toast弹框
Jun 08 Javascript
js移动端图片压缩上传功能
Aug 18 Javascript
vue 自定义组件 v-model双向绑定、 父子组件同步通信的多种写法
Nov 27 Javascript
修改UA在PC中访问只能在微信中打开的链接方法
Nov 27 Javascript
vue之debounce属性被移除及处理详解
Nov 13 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
PHP运行模式的深入理解
2013/06/03 PHP
PHP的伪随机数与真随机数详解
2015/05/27 PHP
PHP 的Opcache加速的使用方法
2017/12/29 PHP
ThinkPHP5.0框架控制器继承基类和自定义类示例
2018/05/25 PHP
php/JS实现的生成随机密码(验证码)功能示例
2019/06/06 PHP
在JavaScript中,为什么要尽可能使用局部变量?
2009/04/06 Javascript
JS小游戏之仙剑翻牌源码详解
2014/09/25 Javascript
jQuery应用之jQuery链用法实例
2015/01/19 Javascript
javascript实现捕捉键盘上按下的键
2015/05/05 Javascript
JS实现横向拉伸动感伸缩菜单效果代码
2015/09/04 Javascript
跟我学习javascript的var预解析与函数声明提升
2015/11/16 Javascript
select下拉框插件jquery.editable-select详解
2017/01/22 Javascript
微信小程序的线程架构【推荐】
2019/05/14 Javascript
vue.js实现备忘录demo
2019/06/26 Javascript
JavaScript面向对象核心知识与概念归纳整理
2020/05/09 Javascript
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
[13:56]DAC2018 4.5SOLO赛决赛 MidOne vs Paparazi第一场
2018/04/06 DOTA
python实现k均值算法示例(k均值聚类算法)
2014/03/16 Python
Python获取远程文件大小的函数代码分享
2014/05/13 Python
Python生成随机MAC地址
2015/03/10 Python
python实现二维数组的对角线遍历
2019/03/02 Python
python图的深度优先和广度优先算法实例分析
2019/10/26 Python
解决Python spyder显示不全df列和行的问题
2020/04/20 Python
利用4行Python代码监测每一行程序的运行时间和空间消耗
2020/04/22 Python
Python基础进阶之海量表情包多线程爬虫功能的实现
2020/12/17 Python
使用CSS禁止textarea调整大小功能的方法
2015/03/13 HTML / CSS
八项规定整改措施
2014/02/12 职场文书
服装促销活动方案
2014/02/23 职场文书
2014中考励志标语
2014/06/05 职场文书
党员干部批评与自我批评反四风思想汇报
2014/09/21 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
公务员政审材料
2014/12/23 职场文书
优秀学生干部事迹材料
2014/12/24 职场文书
技术负责人岗位职责
2015/02/10 职场文书
大学生,三分钟即兴演讲稿
2019/07/22 职场文书
Python中tqdm的使用和例子
2022/09/23 Python