深入浅析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 相关文章推荐
Prototype Array对象 学习
Jul 19 Javascript
JS 文件传参及处理技巧分析
May 13 Javascript
javascript实现鼠标拖动改变层大小的方法
Apr 30 Javascript
JS实现设置ff与ie元素绝对位置的方法
Mar 08 Javascript
jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签
Mar 29 Javascript
Bootstrap自动适应PC、平板、手机的Bootstrap栅格系统
May 27 Javascript
解决node.js安装包失败的几种方法
Sep 02 Javascript
AngularJS入门教程一:路由用法初探
May 27 Javascript
Vue项目webpack打包部署到Tomcat刷新报404错误问题的解决方案
May 15 Javascript
详解使用mocha对webpack打包的项目进行&quot;冒烟测试&quot;的大致流程
Apr 27 Javascript
JavaScript直接调用函数与call调用的区别实例分析
May 22 Javascript
axios封装与传参示例详解
Oct 18 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
【动漫杂谈】关于《请在T台上微笑》
2020/03/03 日漫
PHP中运用jQuery的Ajax跨域调用实现代码
2012/02/21 PHP
destoon安装出现Internal Server Error的解决方法
2014/06/21 PHP
php使用substr()和strpos()联合查找字符串中某一特定字符的方法
2015/05/12 PHP
php自动载入类用法实例分析
2016/06/24 PHP
实例讲解PHP表单处理
2019/02/15 PHP
表单提交时自动复制内容到剪贴板的js代码
2007/03/16 Javascript
javascript 函数调用的对象和方法
2010/07/01 Javascript
JavaScript高级程序设计阅读笔记(六) ECMAScript中的运算符(二)
2012/02/27 Javascript
jquery实现在页面加载完毕后获取图片高度或宽度
2014/06/16 Javascript
Jquery+ajax+JAVA(servlet)实现下拉菜单异步取值
2016/03/23 Javascript
JavaScript弹窗基础篇
2016/04/27 Javascript
如何让一个json文件显示在表格里【实现代码】
2016/05/09 Javascript
jquery分隔Url的param方法(推荐)
2016/05/25 Javascript
Bootstrap轮播插件中图片变形的终极解决方案 使用jqthumb.js
2016/07/10 Javascript
如何将 jQuery 从你的 Bootstrap 项目中移除(取而代之使用Vue.js)
2017/07/17 jQuery
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
如何抽象一个Vue公共组件
2017/10/17 Javascript
浅谈 Webpack 如何处理图片(开发、打包、优化)
2019/05/15 Javascript
微信小程序实现点击效果
2019/06/21 Javascript
vue实现拖拽效果
2019/12/23 Javascript
[01:22:29]真视界:2019年国际邀请赛总决赛
2020/01/29 DOTA
Python 基础教程之包和类的用法
2017/02/23 Python
详解python 字符串和日期之间转换 StringAndDate
2017/05/04 Python
Python matplotlib画图实例之绘制拥有彩条的图表
2017/12/28 Python
解决Python plt.savefig 保存图片时一片空白的问题
2019/01/10 Python
Python字符串大小写转换拼接删除空白
2019/09/19 Python
opencv3/C++实现视频背景去除建模(BSM)
2019/12/11 Python
Jmeter HTTPS接口测试证书导入过程图解
2020/07/22 Python
利用CSS3实现圆角的outline效果的教程
2015/06/05 HTML / CSS
JACK & JONES瑞典官方网站:杰克琼斯欧式风格男装
2017/12/23 全球购物
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
高校生生产实习自我鉴定
2013/09/21 职场文书
测绘专业大学生职业生涯规划书
2014/02/10 职场文书
五年级作文之想象作文
2019/10/30 职场文书
oracle索引总结
2021/09/25 Oracle