Augular初探
一年多前,巧遇angular,觉得是个非常优秀的mv*框架,当时项目使用了MooTools.因此也没继续研究。刚好最近,同事组中有用到ng,并且要做个分享。因此就将from Why Does Angular.js Rock?
重新看了遍,加之中文的翻译有点问题,就在原有翻译基础上,做了点改动。顺便把丢失的图片给补充下。--last update at 20150915
PS:斜体加粗为新增/改动内容
原demo的例子都在plunker上,传送门: http://plnkr.co/users/greengerong,自己用runjs做另一个类似的
将自己写的本地demo上传,demo下载
http://angular-tips.com/blog/2013/08/why-does-angular-dot-js-rock/
惭愧,一天多年前说要完成的翻译,最终还是泡汤了。百度了下,发现已经有很多版本的翻译了,转载吧。
angular为什么如此火
让我们看看下面的介绍就知道原因了:)
Angular.js 是一个MV*(Model-View-Whatever,不管是MVC或者MVVM,统归MDV(model Drive View))JavaScript框架,其是Google推出的SPA(single-page-application)应用框架,其为我们的web应用开发增加不少魔法变换。
我可以花整天的时间告诉你为什么你必须在新项目尝试angular.js,但是我觉得还是百说不如一练。
数据绑定和scopes(作用域)
首先第一个浮出大脑的问题是:angular支持数据绑定吗?
下面让我们来了解angular.js的数据绑定:
<body ng-app>
<span>Insert your name:</span>
<input type="text" ng-model="user.name" />
<h3>Echo: {{user.name}}</h3>
</body>
在这代码片段中,在我们解释细节之前,我还是希望尝试下其效果:
注:此刻暂时不要太心急去了解ng-app。
如你所见,我在input中输入的将会显示在后边echo。这是如何工作的?简单来说,angular的ng-model(更多关于指令的将在文章后续)给我带来了双向绑定机制。
如此是好,但是user.name存储在哪里呢?其存储在我们的$scope上,当我们在input中输入任何字符都会及时的更新scope对象上的user.name属性。然后我们可以利用angular的表达式{{...}}现实在HTML中。所以当我们在input中输入时,其会及时更新scope上的user,name属性,在由修改HTML显示。
好吧,这并不难,但是你所说的$scope是个什么东东呢?在angular中$scope是连接controllers(控制器)和templates(模板view/视图)的主要胶合体。我们可以把我们的model存放在scope上,来达到双向你绑定。
这就好比:
这意味着我们我们从template上为$scope设置了一个属性对象user.name,所以我们也可以在controller中访问这个对象(user.name).
让我们来看个更复杂的示例:
var app = angular.module('app', []); app.controller('MainCtrl', function($scope) {
$scope.message = 'World';
});
<body ng-app="app" ng-controller="MainCtrl">
Hello, {{ message }}
</body>
在这里首先我们定义了angular application,只是简单的创建了一个angular module,其接受一个module名字和依赖数组为参数。
紧接着创建了一个controller,通过调用 app module的controller方法,并传入一个controller 名字和function。function函数接受$scope参数(可以接受更多的参数,放在后面部分)。所以我们可以开始双向绑定了。
在$scope中我们附加了message的字符串属性。
在view中你可能注意到了body tag多出了一些东东,这是干什么的?这些是angular的指令(directives),它给HTML带来了新的语法扩展,在这例子中我们使用了两个angular内置的指令:
ng-app:它会告诉angularbody节点包含了我们的angular应用,换句话说,在body中的一切会被angular所接受管理。其参数为我们的app module的名字,和我们在javascript中命名一致。
ng-controller:在这指令在我们传入的是controller 名字,此例中为MainCtrl。
最后我们将message插入我们的remplate。
所以其可视化表示将是:
聪明的你可以会冒出一个疑问:我们能够在$scope上绑定function?
当然。
var app = angular.module('app', []); app.controller('MainCtrl', function($scope) {
$scope.greet = function() {
$scope.message = "Hello, " + $scope.user.name;
}
});
<body ng-app="app" ng-controller="MainCtrl">
What's your name?:
<input type="text" ng-model="user.name" />
<button ng-click="greet()">Click here!</button>
<h3>{{ message }}</h3>
</body>
我在示例controller中很容易了解到如何添加function到$scope。示例中function将修改$scope.message为“hello ,”和从input输入的$scope.user.name的字符串连接。
然后在HTML中创建一个附加了angular bg-click 指令的button。ng-click指令是的button在被点击时会执行我们为其赋值的greet()表达式。
注意:在input中enter并不会工作,这是展示ng-click如何工作。
指令
我们已经看见了一些指令了,指令是个什么东东?
指令为HTML引入了新的语法。HTML已经很强大了,但是有时我需要更多...
看下面的例子:
<body> <div id="chart"></div> </body>
示例代码在做什么?除了看见id外,我真的什么也不能获知。
然后我们只得从多余30个javascript文件中去查找,最后我们看见如下代码:
$('#chart').pieChart({ ... });
Aha!原来是个饼图(pie chart)容器。
在这里如果你不去查找javascript文件将无法获知页面到底是做什么的,实现了什么功能。
下面我们再来看看angular code,
<body> <pie-chart width="400" height="400" data="data"></pie-chart> </body>
是不是语义很清晰,我们可以一眼看出这是一个pie chart,不仅如此,而且还知道width,height,以及其数据。
如果你对pie chart 示例感兴趣,请猛击这里
angular内置指令
angular给我带来了大量的内置指令。我们已经在前面看见了ng-app,ng-controller,ng-click,ng-model(angular的内置指令都以ng开始),接下来让我了解更多的内置指令。
有时在页面中有部分内容我们只希望到达某状态(属性为true)才显示:
<button ng-click="show = !show">Show</button>
<div ng-show="show">
I am only visible when show is true.
</div>
ng-show仅当angular其表达式值为true时,才显示该元素或子元素。
注意:在这里对于ng-click我们并不是直接在controller中创建function(此刻我们没真正的controller),利用angular表达式作为指令的参数。在首次表达式为undefined,然后我们设置为为true,在false如此交替。
angular同时也提供了ng-hide指令。
让我们看些更有趣的指令,如果有个List或者数组呢?
ar app = angular.module('app', []); app.controller('MainCtrl', function($scope) {
$scope.developers = [
{
name: "Jesus", country: "Spain"
},
{
name: "Dave", country: "Canada"
},
{
name: "Wesley", country: "USA"
},
{
name: "Krzysztof", country: "Poland"
}
];
});
<body ng-app="app" ng-controller="MainCtrl">
<ul>
<li ng-repeat="person in developers">
{{person.name}} from {{person.country}}
</li>
</ul>
</body>
显示结果
棒极了,我们在controller中定义了一个list对象,在HTML用ng-repeat就能简单的显示了。
它是如何工作的?
ng-repeat会为集合中的每一项创建一个新的模板,在示例中有四项数据,将会重复创建下面code四次,
<li ng-repeat="person in developers"> {{person.name}} from {{person.country}} </li>
每次复制都会创建自己新的scope,我们没有为每项手动创建scope,我们可以把scope理解为其scope,但是在这里我们仍然能够访问父scope。
可视化的展示为:
我们能自定义directive?
当然,我们能以不同粒度方式创建angular的directive,例如modal dialogs accordions, paginators, charts,search from ...
angular指令总是与可视化有关?不,我们仍然可以创建一些非可视化的指令集。
让我们来看一个例子吧:
回到我们上面的greet示例:
<body ng-app="app" ng-controller="MainCtrl"> What's your name?: <input type="text" ng-model="user.name" /> <button ng-click="greet()">Click here!</button> <h3>{{ message }}</h3> </body>
已经能够很好的工作了,但是我们希望能够在页面初始化的时候光标焦点聚焦在输入框input。jQuery?jQuery提供了focus函数,能够很简单的完成,但是这里是angular教程,所以我们需要以angular way,显得我们更专业些...
同时我们也希望我们的HTML能够有自描述能力(译者注:现代软件开发特别语言语义更重要,如linq,guava,restfull...) ,所以angular directive肯定是个好的选择。
app.directive('focus', function() { return { link: function(scope, element, attrs) { element[0].focus(); } }; });
接下来,我们可以在可以HTML中标注angular directive(angular directive首字母小写驼峰命名,在前台转换为全小写-分割风格)。
directive是angular中最复杂的要点,这里只是最简单的directive而已,如果可能这将放在以后文章,这里并不会深入。
directive需要一个object的返回对象,我们可以定义一些需要关注的属性,在示例中我们返回了一个link的链接函数(link函数主要作为directive的行为绑定), 我们如果需要,也可以替换HTML中模板。
Link function有3个参数(准确应该是是4个)scope,节点element,还有所有HTML attribute iAttrs。在link函数里我们可以绑定click,mouseenter等事件,注册指令行为。
在示例中我们为指令节点使用了focus操作。对element了解更多,你可以移步到这里。
我们可以很简单的使用指令如下:
<body ng-app="app" ng-controller="MainCtrl"> What's your name?: <input type="text" focus ng-model="user.name" /> <button ng-click="greet()">Click here!</button> <h3>{{ message }}</h3> </body>
目前我们看见的directive都很简单,如何利用指令渲染上面说的固定模板呢?
如下:
app.directive('hello', function() { return { restrict: "E", replace: true, template: "<div>Hello readers, thank you for coming</div>" } });
这里返回的是带有一些attribute的object。
restrict:指令的使用方式
Attribute 形如:<div foo></div>.
Element 形如:<foo></foo>
Class 形如: <div class=”foo”></div>
CoMment 形如: <!-- directive: foo -->
replace:询问是不是需要利用我们的模板替换原来的节点。
template:我们需要append或者replace到原节点的html模板。
directive还有很多的可配置options,如编译compile,template url ...
在示例我们不需要行为的绑定,所有没有link function。其使用如下:
<hello></hello>
不出意外,你会发现<hello></hello>被<div>Hello readers, thank you for coming</div>所代替了
Filters(过滤器)
假想我们有个购物车的view显示如下:
<span>There are 13 phones in the basket. Total: {{ 1232.12 }}</span>
我们如何利用angular表达式显示为货币格式?形如:$1,232.12。
相当简单,angular为我们提供了叫filter得东东,过滤器其好比unix中的管道pipeline。angular同时也内置了货币currency filter.
<span>There are 13 phones in the basket. Total: {{ 1232.12 | currency }}</span>
结果就变成这样了:$1,232.12
如你所见,我们可以用| 使用filter,这和unix管道模型很相似。我们也可以使用|链接更多的filter。
例如我们可以对开发人员简单排序,在用ng-repeat显示出来:
<ul> <li ng-repeat="person in developers | orderBy:'name'"> {{ person.name }} from {{ person.country }} </li> </ul>
在这里你发现了一些很有趣的事?我们可以给filter传递参数!
OrderBy filter会接受一个属性名,并以它进行排序,示例中我们使用 name,如果你希望反序排列,你可以用 -name表示。
马上你可能会冒出你头脑:假想我们不止4个开发人员,有300,并且我们希望通过 name,country过滤呢?
非常简单:
<body ng-app="app" ng-controller="MainCtrl"> Search: <input ng-model="search" type="text" /> <ul> <li ng-repeat="person in developers | filter:search"> {{ person.name }} from {{ person.country }} </li> </ul> </body>
在示例中请注意我们是如何绑定search.name的,此处利用name 做filtering。filter的参数不会改变,绑定是search对象,会根据我们在input中输入改变,而filter则会找寻search对象中的name属性。
到这里我希望你也像我一样一样兴奋起来了!
下面我们来自定义filter呢?实现单词首字母大写 filter:
app.filter('capitalize', function() { return function(input, param) { return input.substring(0,1).toUpperCase()+input.substring(1); } });
这里我们自定义了一个filter其接受输入参数input和过滤器参数param的一个函数。
接下来我们将在view使用它:
<span>{{ "this is some text" | capitalize }}</span>
显示结果:
This is some text
Services
在文章最后,我们需要再次较少下services。这是一个的维护应用程序功能逻辑部分,他是一个单间模式singleton。
为了保持应用程序的逻辑层次分明,更趋向于将其业务逻辑放到不同的services,保持controller的逻辑只有流程控制和view交互逻辑。
angular内置了很多services,如$http http请求,$q 异步promises编程模式...在这里我们不会讨论angular的内置services,由于有很多的services,并且很难一次性解释完,将在后续文章。我们将创建一个简单的自定义services。
在controller之间共享数据对我们很有用,每个controller都有自己的scope所以我们不能将其绑定到其他的controller。所以解决方案是services,可以吧数据共享到services,在需要用到的地方引用它。
首先我们来看看如果不用services,我们将会遇见什么问题:
<div ng-controller="MainCtrl"> MainCtrl: <input type="text" ng-model="user.name"> </div> <div ng-controller="SecondCtrl"> SecondCtrl: <input type="text" ng-model="user.name"> </div>
app.controller('MainCtrl', function($scope) { }); app.controller('SecondCtrl', function($scope) { });
我们使用了相同的ng-model,预期当一个input改变时候会及时更新到另一个input,如下:
但是实际情况却是:
接下来需要借助services来解决这个问题,利用services将user name在controller之间共享。
app.factory('UserInformation', function() { var user = { name: "Angular.js" }; return user; });
这里用的是factory去创建一个service。angular中还有其他更高级的方式去创建service,如service,provider,这将会在后续文章详解。
这里有很多方式去创建service,我们选择的是创建了一个带有name默认值的user对象,并返回它。
在controllers中如何去使用呢?如下:
app.controller('MainCtrl', function($scope, UserInformation) { $scope.user = UserInformation; }); app.controller('SecondCtrl', function($scope, UserInformation) { $scope.user = UserInformation; });
现在我们的程序形如:
酷极了,它工作了,工作了。
现在我们的$scope.user在MainCtrl和SecondCtrl都用的是UserInformation,并且service是单例的,所以当我们更新其中一个controller的时候,另外一个也将会被更新。也有你又有了一个疑问:UserInformation参数是从哪里来的?
angular核心是DI(依赖注入)在需要使用的地方会自定注入service。DI将不会在本节中讲述,我们可以简单的说,你创建了一个service,你可以在module作用域的controller,directive,甚至是其他service作为参数来轻松使用。
也许你对上面出现的$scope认为他也是个service,其实这是一个例外,其并不是真正的service注入到我们的controller。
中文翻译原文:http://www.cnblogs.com/whitewolf/archive/2013/08/11/3251889.html
Augular初探的更多相关文章
- Vue.js 2.0 和 React、Augular等其他框架的全方位对比
引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...
- 初探领域驱动设计(2)Repository在DDD中的应用
概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...
- CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探
CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...
- 从273二手车的M站点初探js模块化编程
前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数 ...
- JavaScript学习(一) —— 环境搭建与JavaScript初探
1.开发环境搭建 本系列教程的开发工具,我们采用HBuilder. 可以去网上下载最新的版本,然后解压一下就能直接用了.学习JavaScript,环境搭建是非常简单的,或者说,只要你有一个浏览器,一个 ...
- .NET文件并发与RabbitMQ(初探RabbitMQ)
本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址:http://www.cnblogs.com/tdws/p/5860668.html 想必MQ这两个字母对于各位前辈们和老司 ...
- React Native初探
前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...
- 【手把手教你全文检索】Apache Lucene初探
PS: 苦学一周全文检索,由原来的搜索小白,到初次涉猎,感觉每门技术都博大精深,其中精髓亦是不可一日而语.那小博猪就简单介绍一下这一周的学习历程,仅供各位程序猿们参考,这其中不涉及任何私密话题,因此也 ...
- Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用
一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性 ...
随机推荐
- longest-substring-with-at-least-k-repeating-characters
https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/ public class S ...
- c#递归生成XML
递归方法大家应该都很熟悉了,简而言之就是方法内部调用自己,就这样不断重复重复再重复的执行, 不过要担心死循环哟... 当我们系统需要动态生成菜单时,也就是说我们系统的菜单是存在数据库中的,数据库结构类 ...
- bind原理图释
(原文:http://blog.think-async.com/2010/04/bind-illustrated.html) 本文解释了bind 是如何工作的.为了清晰,我对图中的语法作了一些简化(例 ...
- Volley框架的介绍使用
Volley是在2013年的Google I/O 2013大会上发布的,是我们的网络通信更快,更简单,更方便.对于初学者来讲是一个很好的框架. 简单来说,它提供了如下的便利功能: JSON,图像等的异 ...
- Spark性能优化(2)——广播变量、本地缓存目录、RDD操作、数据倾斜
广播变量 背景 一般Task大小超过10K时(Spark官方建议是20K),需要考虑使用广播变量进行优化.大表小表Join,小表使用广播的方式,减少Join操作. 参考:Spark广播变量与累加器 L ...
- 【MySQL】MySQL-主从复制-集群方案-数据一致性问题解决方案 && MySQL备份的各种姿势
1.写性能如何保证:分库分表 2.读性能如何保证:主从结构,实时备份 3.一致性问题怎么解决: 3.1.微博案例:Redis缓存,热数据查询走Redis,主从的延迟通过Redis消除 3.2.支付宝的 ...
- cognos report在做同比时遇到的问题解决方法
本例就拿简单的一个模型作为测试: 订单中包括日期key,商品类型key 现在要实现每月的订单数,以及去年同期的订单数: step1:新建2个数据项 本月,去年同月 本月: [每日订单数据分析].[日期 ...
- 如何在MVC的ActionLink中应用Resource文件
项目中建立Resources文件夹. 添加Resource文件,必须添加一个默认的,其他语言可以添加很多个.我这里只添加了一个中文的. 双击每个资源文件,将Access Modifier 设置成pub ...
- 彻底解决 intellij IDEA 卡顿 优化笔记
由于工作中经常出现分支各种切换,使用Eclipse便不再像以前那么舒服了,不停的修改工作空间,每次修改完工作空间又是一堆一堆的个性化设置,来回的切换,真的很累.我们做软件的,怎么能不去尝试新鲜的呢,毕 ...
- PHP高级教程-多维数组
PHP 多维数组 一个数组中的值可以是另一个数组,另一个数组的值也可以是一个数组.依照这种方式,我们可以创建二维或者三维数组: 实例 <?php // 二维数组: $cars = array ( ...