(翻译)Angular.js为什么如此火呢?

在本文中让我们来逐步发掘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的数据绑定:

Edit in plucker

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

让我们来看个更复杂的示例:

Edit in plunker

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?

当然。

Edit in plunker

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)才显示:

Edit in plunker

<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或者数组呢?

Edit in plunker

var 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了解更多,你可以移步到这里

我们可以很简单的使用指令如下:

 Edit in plunker

<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。其使用如下:

Edit in plunker

<hello></hello>

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>

如你所见,我们可以用| 使用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过滤呢?

非常简单:

Edit in plunker

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

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中如何去使用呢?如下:

Edit in plunker

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。

总结:

   到这里我们完成了第一篇但不是最后一篇angular博客。

   Angular.js是一个优秀的框架,我敢肯定你也爱上了它。希望能在下片文章中仍然能见到你的倩影。

   希望你能enjoyed这篇文章,也能够评论些你的观点。

   英语原文来自:http://angular-tips.com/blog/2013/08/why-does-angular-dot-js-rock/

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/p/angularjs-start.html

时间: 2024-08-30 01:17:06

(翻译)Angular.js为什么如此火呢?的相关文章

angular.js之路由的选择方法_AngularJS

在一个单页面中,我们可以添加多个模块,使得网页只在需要的时候加载这个模块.模块的切换大致上可以代替网页的切换,于是,我们便可以通过模块的切换实现网页的切换,这个切换是按需加载的. 乍一看非常普通的东西,但是仔细想想就可以发现,这种思想可以解决非常多的资源. 例如,假如有一个页面,需要显示1000种商品的信息,每个商品的表现形式各不相同(设他们有各自独立的css和js),那么一般来说,我们就需要准备1000张网页去加载这些信息.但是,使用这种模块化思想,我们就可以仅仅在后台设定1000个各不相同的

三大JS框架的较量:Angular.js与React.js与Ember.js

通过选择合适的JavaScript框架来更好适配你的项目需求,这有利于提高你的开发能力与web apps的竞争力. 然后,你可以为基于JavaScript的应用或者网站想个极佳的主意.选择合适框架应该对你项目的成功有显著效果.它可以推到你及时完成项目,并且有助于你将来维护代码.JavaScript框架,比如Angular.js,Ember.js,或者React.js,能提供很好的代码框架,并且保持代码的组织性,从而使得你的app更具灵活性与可扩展性,开发过程更加容易. JavaScript场景的

activiti自定义流程之整合(二):使用angular js整合ueditor创建表单

注:整体环境搭建:activiti自定义流程之整合(一):整体环境配置 基础环境搭建完毕,接下来就该正式着手代码编写了,在说代码之前,我觉得有必要先说明一下activit自定义流程的操作. 抛开自定义的表单不谈,通过之前的了解,我们知道一个新的流程开始,是在启动流程实例(processIntence)的时候,而流程实例依赖于流程定义(processDefinition),流程定义又依赖于流程模型(model). 我们用到的自定义表单需要在创建模型,画模型图的时候就指定表单的名称formKey,需

Angular.js与Bootstrap相结合实现表格分页代码_AngularJS

先给大家简单介绍angular.js和bootstrap基本概念. AngularJS 是一个 JavaScript 框架.它可通过 <script> 标签添加到 HTML 页面. AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑定数据到 HTML. Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷. 最近一直学习Angular.js,在学习过程

Angular.js与Bootstrap相结合实现手风琴菜单代码_AngularJS

标题定的是angularjs与bootstrap相结合实现手风琴菜单,其实也就是用的bootstrap的样式. 在上篇文章给大家介绍了Angular.js与Bootstrap相结合实现表格分页代码.接着学习实现的Demo. 主要练习自定义指令,向指令中传递参数,老规矩先上效果图: <my-page ng-repeat="item in expanders" page-title="item.title">{{item.text}}</my-page

Angular.js回顾ng-app和ng-model使用技巧_AngularJS

Angular.js中index.html简单结构: <!doctype html> <html ng-app> <head> <script src="http://code.angularjs.org/angular-1.0.1.min.js"></script> </head> <body> Your name: <input type="text" ng-model=&

如何在Angular.JS中接收并下载PDF_AngularJS

介绍 jsPDF 是一个使用Javascript语言生成PDF的开源库.你可以在Firefox插件,服务端脚本或是浏览器脚本中使用它. 客户端Safari 和 iPhone Safari 支持得最好,其次是Opera和Windows下的Firefox 3等.IE暂不支持. 示例代码: var doc = new jsPDF(); doc.text(20, 20, 'Hello world.'); doc.save('Test.pdf'); 服务器端可以完美运行. jsPDF使用方便,但是不支持中

路由-angular js的设置跳转权限

问题描述 angular js的设置跳转权限 angularjs 中路由设置跳转权限,我在url后面动态添加一串数字,怎么让他不跳转到其他的默认页面,在白名单中怎么加入这个url 解决方案 http://www.open-open.com/lib/view/open1408084201582.html

angular.js 嵌套路由

介绍 AngularJS 嵌套路由:,来看看嵌套的ui-router状态是怎么回事. ui-router和同属AngularJS框架一部分的ng-route一样强大. ui-router提供了让我们可以做路由嵌套和视图命名的特性. 我们将在示例中看到ui-router中存在的所有类型. 背景 引述我之前那篇文章开头给出的使用ui-router框架实现的简单路由, 基于我们的业务需求,需要有不同类型的导航, 一般像那种从一个页面到另外一个页面的导航非常的普通.但请想象一下在某些情况下,你需要在一个