AngularJS —— 使用模块组织你的代码 【已翻译100%】(2/3)

简介:

函数是一个对象:它创建了范围

这是因为现在你已经把isDoingWork这个变量创建在了一个函数里面 -- 也就是我们们的匿名 IIFE 中 -- 而如此这个变量就只能通过这个函数才能访问到. 有趣的是Javascript中的所有函数都是第一类对象. 那很简明的意味着函数是一个对象,它可能通过一个变量被访问到. 或者说,另外一种描述的方式是你存储了指向 函数的一个引用,并在稍后的某个时间获取其变量.

在我们第一个示例中,我们的问题是并没有保存一个指向我们匿名函数的引用,所以我们永远也不能再获取到isDoingWork这个值。这就是我们下一个示例要改进的地方.

函数是一个对象 : 使用this

因为每一个函数都是一个对象,所以每个函数都会有一个this变量,这个变量向开发者提供了指向当前对象的引用. 为了提供在从外部大我们的函数及其范围的访问,我们可以返回这个this变量 -- 而它将会提供一个指向当前对象的引用.

然后,除非我们将这个私有的isDoingWork变量添加到函数引用(this)上,我们也不能够引用这个变量。为此我们要对之前的示例做一下轻微的改动。它看起来会像下面这样:

thing = (function(){  // 1.
   this.isDoingWork = false; // 2.
   console.log("isDoingWork value : " + isDoingWork);
   return this; // 3.
}());

你可以看到第一行我们加入了一个新的全局变量thing,它包含了从匿名函数返回的值。从示例代码的开头跳到第三行,你可以看到我们返回了this变量。那就意味着我们返回了一个指向匿名函数的引用.

在第二行我们也已经将isDoingWork加入了this引用中,那样我们就可以使用语法thing.isDoingWork来从外部引用到这个值了.

自己动手看看

为了看看的运行,你可以做下面这几步:

1.下载本文的示例代码.

2.在你的浏览器中打开 modulePattern4.htm.

3.打开浏览器开发工具 -- F12(Chrome, IE) 或者 Ctrl-Shift-I (Opera) -- (那样你就可以看到控制台了)

4.你将会看到isDoingWork的值会输出到控制台,就像最开始那个示例中你看到的那样.

5.不过,现在你得输入thing.isDoingWork才能或者这个值.

模块模式总结

在最后这个示例中,变量值被成功的封装了,而其他的JavaScript库则可以明确的引用thing对象来获取这个值. 好像不大可能,而这帮助了我们保持全局命名空间的干净,并且在看起看来是更好的代码组织形式. 这也使得我们代码的维护更容易.

最终,我们用上了 AngularJS

因为使用模块模式是一个最佳实践,AngularJS的开发者就将一个模块系统构建到了库中.

Plunker 代码

首先你可以通过到这个Plunker上 (http://plnkr.co/edit/js8rbKpIuAuePzLF2DcP?p=preview - 在一个新的窗口或Tab页打开)获取整个AngularJS示例.

而我们在这里展示出代码,那样我们就可以更方便的谈论它了.

首先,让我们看看这个 HTML.

<!DOCTYPE html>
<html ng-app="mainApp">

  <head>
    <meta charset="utf-8" />
    <title>Angular Module Example</title>
    <script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.20/angular.js" data-semver="1.2.20"></script>
    <script src="mainCtrl.js"></script>
    <script src="secondCtrl.js"></script>
  </head>

  <body>
    <div ng-controller="MainCtrl as mc">
      <p>mc refers to MainCtrl which has 
      been added to the angular app module</p>
      <p>Hello {{mc.name}}!</p>
      <ol><li ng-repeat="a in mc.allThings">{{a}}</li></ol>
    </div>
    <div ng-controller="SecondCtrl as sc">
      <p>
        Hello {{sc.name}}
      </p>
      <ol><li ng-repeat="a in sc.allThings">{{a}}</li></ol>
    </div>
  </body>

</html>

Angular 指令 : ng-app

Angular 所定义和使用的东西叫做指令。这些指令基本上就是由Angular定义属性,而AngularJS编译器(Angular的JavaScript)会将它们转换成其他的东西.

我们应用了ng-app指令,为我们的Angular应用定义了一个名称,叫做mainApp.

mainApp 就是我们稍后会看到的模块模式的起点.

被引入的脚本 : 每个都是一个模块

现在,请注意有三个脚本被引入到了这个HTML中.

第一个是必须的AngularJS库.

而其他两个则是作为模块被实现的Angular控制器.

它们被作为模块实现以保持代码彼此,还有从这个应用上看,都是独立的.

AngularJS : 创建 score

在往下看,你将会看到两个以如下代码开头的div:

<div ng-controller="MainCtrl as mc">
<div ng-controller="SecondCtrl as sc">

这是在为div的每一个都设置上ng-controller. 这些div中的每一个都有其各自的范围. 第一个控制器的名字叫做 MainCtrl,第二个叫做 SecondCtrl.

AngularJS 编译器会在你提供(引入)的代码中用这两个名称查找对应的函数.

如果AngularJS编译器没有找个这两个名称对应的函数,它就会抛出一个错误.

mainCtrl.js : 第一个控制器

让我们来看看mainCtrl.js文件里面有些啥东西.

你可以在Plunker页面的左侧点击它在Plunker中将其打开.

当你打开了它,你将会看到一些看上去很熟悉的代码。好吧,你至少会看出来它们都是被包在一个IIFE中的.

(function() {

  var app = angular.module(&apos;mainApp&apos;, []);

  app.controller(&apos;MainCtrl&apos;, function() {
    console.log("in MainCtrl...");
    // vt = virtual this - just shorthand
    vt = this;
    vt.name = &apos;MainCtrl&apos;;
    vt.allThings = ["first", "second", "third"];

  });
})();

那是因为我们需要这些代码在文件mainCtrl.js被加载时就运行.

现在,请注意在这个IIFE中的第一行代码.

var app = angular.module(&apos;mainApp&apos;, []);

这行代码是Angular将一个模块添加到其命名空间的方式. 在这里,我们添加了一个将用来展示我们应用程序的模块. 这是应用程序的模块,而我们已经将其命名为 itmainApp, 它跟HTML页面上ng-app所指定的值是一样的.

我们也创建了一个叫做app的(只在IIFE本地可见的)本地变量,以便我们将可以在这个函数内部用来再次添加一个控制器.

奇怪的 Angular 语法

请你也要再仔细看看第一行。你会注意到我们是首次创建mainApp模块,而如果是首次,则我们必须提供以字符串数组的形式提供其可能需要的任何依赖(,表示出依赖库的名称). 不过,在这里对于这个简单的示例而言,我们不需要任何的依赖。但Angular仍然需要我们传入一个空的数组,以便它知晓我们正在创建新的模块,而不是去试图加载一个已经被创建好了的模块.

提示: 你将会看到我们会在secondCtrl.js里加载mainApp模块,而上面所提的数组将会有更多的作用.

我们一把mainApp创建好,就需要向其添加我们的控制器. 这些就是Angular预期我们在HTML(的div中)加入的控制器.

将控制器添加到App模块

添加控制器的代码看起来像下面这样:

app.controller(&apos;MainCtrl&apos;, function() {
    console.log("in MainCtrl...");
    // vt = virtual this - just shorthand
    vt = this;
    vt.name = &apos;MainCtrl&apos;;
    vt.allThings = ["first", "second", "third"];

  });

为了添加我们的控制器函数,我们向app.controller()函数提供了一个控制器名称和一个函数. 在此处我们提供了一个匿名函数.

所以,我们的控制器主体代码就是下面这几行了:

console.log("in MainCtrl...");
   // vt = virtual this - just shorthand
   vt = this;
   vt.name = &apos;MainCtrl&apos;;
   vt.allThings = ["first", "second", "third"];

这里,当我们的控制器运行时,会向控制台输出一行. 然后,我们将this变量重命名为vt(方便起见,就叫他虚拟的this) ,而后我天为其添加了一个name属性和一个叫做allThings 的字符串数组.

控制器和封装

那就是当控制器被Angular调用时会运行的代码. 那个控制器会在文件被加载时运行起来,也就是一开始HTML被加载的时候. 这意味着控制器会被加载到app模块中,而这些属性会被添加到控制器对象(函数)中。因为我们想this变量添加了属性,我们就可以在稍后获取这些属性,但它们是被封装了起来的,因此它们不可以被每个人随意的更改.

现在,让我们跳到HTML中控制器被引用和使用的地方.

第一个Div

这是我们的MainCtrl控制器被引用和使用的第一个Div。它看起来就像下面这样:

<div ng-controller="MainCtrl as mc">
    <p>mc refers to MainCtrl which has 
    been added to the angular app module</p>
    <p>Hello {{mc.name}}!</p>
    <ol><li ng-repeat="a in mc.allThings">{{a}}</li></ol>
 </div>

这个div输出我们的web页面的如下部分,看起来就是接下来这张图片上所展示的那样.

image

相关文章
|
4月前
|
前端开发 JavaScript 开发者
详细介绍 AngularJS 表单的各种特性、用法和最佳实践
详细介绍 AngularJS 表单的各种特性、用法和最佳实践
74 1
|
8月前
|
前端开发
angular2快速构建项目
angular2快速构建项目
61 0
|
11月前
|
缓存 前端开发 JavaScript
「前端架构」Angular的13个主要好处和用例
「前端架构」Angular的13个主要好处和用例
|
JavaScript 前端开发 开发者
前端必知词汇:AngularJS
AngularJS是一个开发动态Web应用的框架,同时也是一个用 JavaScript 编写的库。它可以通过 script 标签添加到网页中,让用户可以使用HTML作为模板语言并且可以通过扩展的HTML语法来使应用组件更加清晰和简洁。自2009年,由Misko Hevery 等人创建,后为Google所收购。目前已经被用于Google的多款产品当中。
442 0
|
JavaScript 测试技术 前端开发
实例解说AngularJS在自动化测试中的应用
本文通过实例介绍AngularJS在自动化测试中的应用。
|
JavaScript 容器 数据挖掘
Angularjs 与三方js插件配合使用,并通过模板动态解析angularjs 语法
在一个静态见面上做数据分析,由于前后端分离 前端使用Angularjs框架,后端使用RESTFUL,如图
2657 0
|
Web App开发 前端开发 JavaScript