一、Angular优点:

1、MVC:职责清晰,代码模块化。

2、模块化

3、指定系统——directive:我们已经在模板中看到了一些新的属性,这些属性不属于HTML规范。例如:我们引入了双花括号用来实现数据绑定;引入了ng-controller用来指定每个控制器负责监视视图中的哪一部分;引入ng-model,用来把输入数据绑定到模型中的一部分属性上。我们把这些指令叫做HTML扩展指令。

4、双向数据绑定

5、依赖注入:进行数据绑定的$scope对象会被自动传递给我们;我们并不需要调用任何函数去创建这个对象。只要把$scope对象放在控制器的构造函数里面,然后就可以获取它了。并且$scope并不是我们唯一可以获取的东西。如果我们想把数据绑定到用户浏览器中的URL地址上,可以使用$location对象,只要把$location对象放到我们的构造函数中即可,例如:

function HelloCtroller($scope,$location) {
$scope.greeting={text:'Hello'};
  //这里可以使用$location对象来做一些很酷的事儿
}

这种神奇的效果是通过angular的依赖注入机制实现的。依赖注入让我们遵守这样一种开发风格:我们的类只是简单获取它们所需要的东西,而不需要创建那些它们所依赖的东西。

二、Model View Controller

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-controller='TextController'>
<p>{{someText.message}}</p>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("TextController",["$scope",function($scope){
var someText={};
someText.message='hahhaha';
$scope.someText=someText;
}]);
</script>
</body>
</html>

其中,<p>{{someText.message}}</p> 采用双花括号插值语法,把新的内容插入到现有的模板中。

控制器就是你所编写的类或者类型,它的作用是告诉Angular该模型是由哪些对象或者基本数据构成的,只要把这些队形或者基本数据设置到$scope对象上即可,$scope对象会被传递给控制器。

通过$scope对象把数据模型和函数暴露给视图(UI模板)。

这个版本中,我们把ng-app属性设置成了模块的名称myApp。然后我们再调用angular对象创建了一个名为myApp的模块,并且把控制器函数传递给了myApp模块的controller函数。

采用模块机制可以把东西从全局命名空间中隔离开。

三、模块和数据绑定

1、表单输入

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form ng-controller = "SomeController">
Starting:<input ng-change='computeNeeded()' ng-model="funding.startingEstimate">
Recommendation:{{funding.needed}}
</form>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("SomeController",["$scope",function($scope){
$scope.funding={startingEstimate:0}; $scope.computeNeeded=function(){
$scope.funding.needed=$scope.funding.startingEstimate*10;
}
}]); </script>
</body>
</html>

对于输入元素说,可以使用ng-change属性来指定一个控制器方法,一旦用户修改了输入元素,这个方法就会被调用。

当用户在这个特定的输入框中输入时,输入框就会正确地刷新。但是,如果还有其他输入框也绑定到模型中的这个属性上,会怎么样呢?如果接受到服务器的数据,导致数据模型进行刷新,又会怎样?

为了能够正确地刷新输入框,而不管他是通过何种途径进行刷新的,我们需要使用$scope中的$watch函数。最基本的一点就是,可以调用$watch()函数来监视一个表达式,当这个表达式发生变化时就会调用一个回调函数。

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form ng-controller = "SomeController">
Starting:<input ng-model="funding.startingEstimate">
Recommendation:{{funding.needed}}
</form>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("SomeController",["$scope",function($scope){
$scope.funding={startingEstimate:0};
computeNeeded=function(){
$scope.funding.needed=$scope.funding.startingEstimate*10;
console.log($scope.funding.startingEstimate);
};
$scope.$watch('funding.startingEstimate',computeNeeded)
}]); </script>
</body>
</html>

请注意,$scope.$watch('funding.startingEstimate',computeNeeded) 需要监视的表达式位于引号中,它是一个字符串。这个字符串会被当做angular表达式来执行。当他的值发生变化时,就调用computeNeeded()。

2、列表、表格以及其他迭代型元素

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-controller='TextController'>
<ul>
<li ng-repeat='student in students'>
<a href="/student/view/{{student.id}}">{{student.name}}</a>
</li>
</ul>
<button ng-click='insertTom()'>Insert</button>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
var students=[{name:'Mary',id:'1'},{name:'Jack',id:'2'},{name:'Jill',id:'3'}];
myApp.controller("TextController",["$scope",function($scope){
$scope.students=students;
$scope.insertTom=function(){
$scope.students.splice(1,0,{name:'Tom',id:'4'})
}
}]);
</script>
</body>
</html>

ng-repeat指令可以通过$index返回当前引用的元素序号;还可以通过$first、$middle、$last,ng-repeat指令返回布尔值,告诉你当前元素是否是集合中的第一个元素、中间的某个元素,或者最后一个元素。

3、隐藏和显示/CSS类和样式

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.menu-disabled-true{background:gray;}
</style>
</head>
<body ng-controller='TextController'>
<button ng-click='toggleMenu()'>Toggle Menu</button>
<ul ng-show='menuState'>
<li class='menu-disabled-{{isDisabled}}' ng-click="stun()">stun</li>
<li ng-click="disintegrate()">disintegrate</li>
<li ng-click="erase()">erase from history</li>
</ul>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("TextController",["$scope",function($scope){
$scope.menuState=true;
$scope.isDisabled=false;
$scope.toggleMenu=function(){
$scope.menuState= !$scope.menuState;
}
$scope.stun=function(){
$scope.isDisabled=true;
} }]);
</script>
</body>
</html>

现在可以动态的设置css类和样式了,只要使用{{}}插值语法把它们进行数据绑定即可。

4、ng-class、ng-style

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.error{
background: red;
}
.warning{
background: yellow;
}
</style>
</head>
<body ng-controller='TextController'>
<div ng-class="{error:isError,warning:isWarning}">
{{messageTxt}}
</div>
<button ng-click="showError()">Simulate Error</button>
<button ng-click="showWarning()">Simulate Warning</button> <script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("TextController",["$scope",function($scope){
$scope.isError=false;
$scope.isWarning=false; $scope.showError=function(){
$scope.messageTxt='This is an error';
$scope.isError=true;
$scope.isWarning=false;
};
$scope.showWarning=function(){
$scope.messageTxt='Just a warning.Please carry on.';
$scope.isWarning=true;
$scope.isError=false;
}
}]); </script>
</body>
</html>

若需要将表格中被选中的行进行高亮显示:

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.selected{background: lightgreen;}
</style>
</head>
<body ng-controller='TextController'>
<table>
<tr ng-repeat='student in students' ng-click='select($index)' ng-class='{selected:$index==selectedRow}'>
<td>{{student.id}}</td>
<td>{{student.name}}</td>
</tr>
</table>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
var students=[{name:'Mary',id:'1'},{name:'Jack',id:'2'},{name:'Jill',id:'3'}];
myApp.controller("TextController",["$scope",function($scope){
$scope.students=students;
$scope.select=function(row){
$scope.selectedRow=row;
}
}]);
</script>
</body>
</html>

在上面中,我们把ng-class设置为{selected:$index==selectRow}。这样做的效果就是,当模型属性selectRow的值等于ng-repeat中的$index时,selected样式就会被设置到那一行上。而ng-click则是告诉控制器用户点击了哪一行。

5、使用$watch 监控数据模型的变化

当你的数据模型中某一部分发生变化时,$watch函数可以向你发出通知。你可以监控单个对象的属性,也可以监控需要经过计算的结果(函数),实际上只要能够被当作属性访问到,或者可以当做一个Javascript函数被计算出来,就可以被$watch函数监控。它的函数签名为:$watch(watchFn,watchAction,deepWatch);

$watch函数会返回一个函数,当你不再需要接收变更通知时,可以用这个返回的函数注销监控器。

将(二)中的购物车功能进行扩充完整。例如,当用户添加到购物车中的商品价值超过100美元时,我们会给他10美元的折扣。如下:

 <!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-controller='CartController'>
<h1>Your Order</h1>
<div ng-repeat='item in items'>
<span>{{item.title}}</span>
<input type="text" ng-model='item.quality'>
<span>{{item.price|currency}}</span>
<span>{{item.price*item.quality|currency}}</span>
<button ng-click='remove($index)'>Remove</button>
</div>
<div>total:{{totalCart()|currency}}</div>
<div>discount:{{bill.discount|currency}}</div>
<div>subtotal:{{subtotal()|currency}}</div>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("CartController",["$scope",function($scope){
$scope.bill={};
$scope.items=[
{title:'Paint pots',quality:8,price:3.95},
{title:'Polka dots',quality:17,price:12.95},
{title:'Pebbles',quality:5,price:6.95}
];
$scope.totalCart=function(){
var total=0;
for (var i = 0,len = $scope.items.length; i<len;i++) {
total=total+$scope.items[i].price*$scope.items[i].quality;
}
return total;
}
$scope.subtotal=function(){
return $scope.totalCart()-$scope.bill.discount;
}
function calculateDiscount(newValue,oldValue,scope){
$scope.bill.discount=newValue>100?10:0;
}
$scope.$watch($scope.totalCart,calculateDiscount);
$scope.remove=function(index){
console.log(index);
$scope.items.splice(index,1)
} }]);
</script>
</body>
</html>

另:watch中的性能注意事项:

上个例子可以正确地运行,但是却潜在性能问题。如果你在totalCart()中打个调试断点,你会发现在渲染这个页面时,该函数被调用了6次。虽然在当前这个应用中它所引起的性能问题并不明显,但是在更加复杂的应用中,运行6次就会成为一个问题。

为什么是6次呢?其中3次我们可以很容易跟踪到,因为在以下每种情况下,它都会运行一次:

  • 模板{{totalCart()|currency}}
  • subtotal()函数
  • $watch()函数

然后angular把以上整个过程又重复了一遍,最终是6次。angular这样做的目的是,检测模型中的变更已经被完整地进行了传播,并且模型已经被设置好。angular的做法是,把所有被监控的属性都拷贝一份,然后把它们和当前的值进行比较,看看是否发生了变化。

有几种方法可以解决这个问题。一种方法是监控items数组的变化,然后重新计算$scope属性中的总价、折扣和小计值。

<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-controller='CartController'>
<h1>Your Order</h1>
<div ng-repeat='item in items'>
<span>{{item.title}}</span>
<input type="text" ng-model='item.quality'>
<span>{{item.price|currency}}</span>
<span>{{item.price*item.quality|currency}}</span>
<button ng-click='remove($index)'>Remove</button>
</div>
<div>total:{{bill.totalCart|currency}}</div>
<div>discount:{{bill.discount|currency}}</div>
<div>subtotal:{{bill.subtotal|currency}}</div>
<script src='angular-1.3.0.js'></script>
<script>
var myApp=angular.module('myApp',[]);
myApp.controller("CartController",["$scope",function($scope){
$scope.bill={};
$scope.items=[
{title:'Paint pots',quality:8,price:3.95},
{title:'Polka dots',quality:17,price:12.95},
{title:'Pebbles',quality:5,price:6.95}
];
$scope.calculateTotals=function(){
var total=0;
for (var i = 0,len = $scope.items.length; i<len;i++) {
total=total+$scope.items[i].price*$scope.items[i].quality;
}
$scope.bill.totalCart=total;
$scope.bill.discount=total>100?10:0;
$scope.bill.subtotal=total-$scope.bill.discount;
};
$scope.$watch("items",$scope.calculateTotals,true);//此处第三个参数传递了一个true,请求angular遍历items的属性,
                                      当其中任何一个属性变化时就调用$scope函数
$scope.remove=function(index){
console.log(index);
$scope.items.splice(index,1)
}
}]);
</script>
</body>
</html>

请注意,上面的代码在调用$watch函数时把items写成了一个字符串。这样做是可以的,因为$watch函数既可以接受一个函数(就像我们之前说的),也可以接受一个字符串。如果把一个字符串传递给了$watch函数,它将会在被调用的$watch作用域中当成表达式来执行。

对于这种应用来说,这种策略可能会工作得很好。但是,既然我们在监控items数组,angular就会制作一份数组的拷贝,用来进行比较操作。对于大型的items数组来说,如果每次在angular显示页面时只需要重新计算bill属性,那么性能会好很多。

可以通过创建一个带有watchFn的$watch函数我们就可以实现这一点,watchFn将会像下面这样来重新计算属性值:

        myApp.controller("CartController",["$scope",function($scope){
$scope.bill={};
$scope.items=[
{title:'Paint pots',quality:8,price:3.95},
{title:'Polka dots',quality:17,price:12.95},
{title:'Pebbles',quality:5,price:6.95}
];
$scope.$watch(function(){
var total=0;
for (var i = 0,len = $scope.items.length; i<len;i++) {
total=total+$scope.items[i].price*$scope.items[i].quality;
}
$scope.bill.totalCart=total;
$scope.bill.discount=total>100?10:0;
$scope.bill.subtotal=total-$scope.bill.discount;
}) $scope.remove=function(index){
console.log(index);
$scope.items.splice(index,1)
}
}]);

Angular(一)的更多相关文章

  1. Angular杂谈系列1-如何在Angular2中使用jQuery及其插件

    jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...

  2. Angular企业级开发(5)-项目框架搭建

    1.AngularJS Seed项目目录结构 AngularJS官方网站提供了一个angular-phonecat项目,另外一个就是Angular-Seed项目.所以大多数团队会基于Angular-S ...

  3. TypeScript: Angular 2 的秘密武器(译)

    本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...

  4. angular实现统一的消息服务

    后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...

  5. div实现自适应高度的textarea,实现angular双向绑定

    相信不少同学模拟过腾讯的QQ做一个聊天应用,至少我是其中一个. 过程中我遇到的一个问题就是QQ输入框,自适应高度,最高高度为3row. 如果你也像我一样打算使用textarea,那么很抱歉,你一开始就 ...

  6. Angular企业级开发-AngularJS1.x学习路径

    博客目录 有链接的表明已经完成了,其他的正在建设中. 1.AngularJS简介 2.搭建Angular开发环境 3.Angular MVC实现 4.[Angular项目目录结构] 5.[SPA介绍] ...

  7. Angular企业级开发(4)-ngResource和REST介绍

    一.RESTful介绍 RESTful维基百科 REST(表征性状态传输,Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来 ...

  8. Angular企业级开发(3)-Angular MVC实现

    1.MVC介绍 Model-View-Controller 在20世纪80年代为程序语言Smalltalk发明的一种软件架构.MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并 ...

  9. Angular企业级开发(2)-搭建Angular开发环境

    1.集成开发环境 个人或团队开发AngularJS项目时,有很多JavaScript编辑器可以选择.使用优秀的集成开发环境(Integrated Development Environment)能节省 ...

  10. 前端MVC学习总结(一)——MVC概要与angular概要、模板与数据绑定

    一.前端MVC概要 1.1.库与框架的区别 框架是一个软件的半成品,在全局范围内给了大的约束.库是工具,在单点上给我们提供功能.框架是依赖库的.AngularJS是框架而jQuery则是库. 1.2. ...

随机推荐

  1. redis安装与简单使用

    第一步 新建一个文件 第二步 利用winscrp软件从本机上传redis的压缩包到linux新建的rdtar目录 第三步   cd rdtar 第四步   解压  tar zxvf redis-2+t ...

  2. 数据分析处理库Pandas——merge操作

    有一列列名相同值也相同 有两列列名相同值也相同 按其中一列合并 按两列合并 有一列列名相同值也相同,有一列列名相同值不相同,按两列合并 列名相同值不相同的行删掉 保留所有行 保留所有行并显示合并后该值 ...

  3. 学习Pytbon第十七篇,面向对象编程

    面向对象技术简介 类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类 ...

  4. 学习python第十三天,函数5 装饰器decorator

    定义:装饰器本质是函数,(装饰其他函数)就是为其他函数添加附加功能原则:1.不能修改被装饰的函数的源代码 2.不能修改装饰的函数的调用方式 实现装饰器知识储备1函数即变量2.高阶函数,满足2个条件之一 ...

  5. POJ 2441 状压DP

    Arrange the Bulls Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 5289   Accepted: 2033 ...

  6. urllib使用四--urlencode,urlparse,

    urllib.urlencode 把字典数据转换为URL编码 # -*- coding: cp936 -*- import urllib params = {'score':100,'name':'爬 ...

  7. Eclipse EE 运行 Myeclipse Web 应用

    第一步:进入项目所在目录,打开.project文件,找到<natures>...</natures>标签,在中间添加如下子标签内容 <nature>org.ecli ...

  8. windows下使用Python出现No module named tkinter.ttk

    1. 编辑工具使用Pycharm,windows平台,运行的时候报错误 2. 目前用的是Python2.7版本,对比了一下已有的库,名字不太一样,因此换成Python3.6的测试一下暂时没这个问题了. ...

  9. [转]全图形PPT设计指南

    三.什么时候使用 全图形PPT并不适用于所有时候,一般来说,我们在以下场合可以考虑使用:陈述一个故事.名人简介.产品介绍.读书笔记.心灵鸡汤.生活情趣等. 四.如何制作全图形PPT 全图形PPT的制作 ...

  10. 《1024伐木累》-小白篇之丽jie(结束篇)-总章节六

    往期回顾:  机缘巧合,月侠发现了老王和他心仪女孩儿的秘密,这让他倍感愤怒,一年以后,丽姐又在去往老王家的路上,这让月侠感到历史即将重新上演,他想拦住丽姐,可恰巧丽姐手机没电,失去了联系. 小序 有人 ...