一年多前,巧遇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>

  显示结果

Jesus from Spain
Dave from Canada
Wesley from USA
Krzysztof from Poland

棒极了,我们在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:指令的使用方式

  1. Attribute 形如:<div foo></div>.

  2. Element 形如:<foo></foo>

  3. Class 形如: <div class=”foo”></div>

  4. 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>

  

按名字排序,结果如下
Dave from Canada
Jesus from Spain
Krzysztof from Poland
Wesley from USA

在这里你发现了一些很有趣的事?我们可以给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初探的更多相关文章

  1. Vue.js 2.0 和 React、Augular等其他框架的全方位对比

    引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...

  2. 初探领域驱动设计(2)Repository在DDD中的应用

    概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...

  3. CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探

    CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...

  4. 从273二手车的M站点初探js模块化编程

    前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数 ...

  5. JavaScript学习(一) —— 环境搭建与JavaScript初探

    1.开发环境搭建 本系列教程的开发工具,我们采用HBuilder. 可以去网上下载最新的版本,然后解压一下就能直接用了.学习JavaScript,环境搭建是非常简单的,或者说,只要你有一个浏览器,一个 ...

  6. .NET文件并发与RabbitMQ(初探RabbitMQ)

    本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址:http://www.cnblogs.com/tdws/p/5860668.html 想必MQ这两个字母对于各位前辈们和老司 ...

  7. React Native初探

    前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...

  8. 【手把手教你全文检索】Apache Lucene初探

    PS: 苦学一周全文检索,由原来的搜索小白,到初次涉猎,感觉每门技术都博大精深,其中精髓亦是不可一日而语.那小博猪就简单介绍一下这一周的学习历程,仅供各位程序猿们参考,这其中不涉及任何私密话题,因此也 ...

  9. Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

    一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性 ...

随机推荐

  1. CentOS6.5升级autoconf版本 Autoconf version 2.64 or higher is required

    安装软件时提示说需要Autoconf 2.64或更高的版本 [root@BobServerStation twemproxy]# autoconf configure.ac:8: error: Aut ...

  2. iOS开发-UITableView常用方法

    UITableView常用来展示数据,类似于Android中的ListView,相对于Android中的ListView而言,UITableView的实现是非常简单,继承UITableViewData ...

  3. Copy List with Random Pointer leetcode java

    题目: A linked list is given such that each node contains an additional random pointer which could poi ...

  4. RV 多样式 MultiType 聊天界面 消息类型 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  5. 使用Spring Security和OAuth2实现RESTful服务安全认证

    这篇教程是展示如何设置一个OAuth2服务来保护REST资源. 源代码下载github. (https://github.com/iainporter/oauth2-provider)你能下载这个源码 ...

  6. 动态装载外部JavaScript脚本文件

    当我们请求一个URL地址时,浏览器会从远程服务器装载各种所需的资源,如JavaScript.CSS.图片等.而在加载JavaScript时,常常会发生下面这种情况: 也就是说,当浏览器碰到Script ...

  7. javascript深度克隆对象

    /** * * @param obj * @returns {*} */ //深度克隆 function cloneObject(obj) { if (obj === null || typeof(o ...

  8. 算法(第四版)学习笔记之java实现希尔排序

    希尔排序思想:使数组中随意间隔为h的元素都是有序的. 希尔排序是插入排序的优化.先对数组局部进行排序,最后再使用插入排序将部分有序的数组排序. 代码例如以下: /** * * @author seab ...

  9. IDEA+Gradle相关资料

    要注意下载的版本,不能过于陈旧,否则会报错,导致无法正常配置. 具体配置参考:https://my.oschina.net/u/1994816/blog/297967 IDEA下载地址:https:/ ...

  10. ZOJ 2320 Cracking' RSA

    其次布尔线性方程组,高斯消元.这道题目的关键部分是看的神牛watashi的思路.另附上watashi的思路 我把他的java模板翻译成了C++的了...存起来以后当模板用...a[i][j]表示第i个 ...