2识angularJS

  前言:记得十月份时下定狠心说天天要翻新1篇博客,学习点新东西,实践下来发现太不具体,生活中的事情很多,再喜欢也不可能让它一件占据生活的百分百吧,所以啊,未来大势所趋吧。以前有1篇‘初识angular’因为离职找工作等一名目繁多原因,搁置了许久,今晚探视,继续写从前的已经力不从心继续,索性重新先河,有时光再修该以前的啊。

贰识angular(基于angular官方文档)

地址:https://angularjs.org/

一,基础:先看html代码

<!doctype html>
<html ng-app><!--ng-app声明页面的这个部分将基于angular-->
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
  </head>
  <body>
    <div>
      <label>Name:</label>
      <input type="text" ng-model="yourName" placeholder="Enter a name here">
      <!--ng-model将表单和模型联系在一起,这里的即yourname,这样你在表单中输入的内容将出现在后文中调用该变量的地方,{{yourName}}-->
      <h1>Hello {{yourName}}!</h1>
    </div>
  </body>
</html>

创设angular应用,首先应该相应引入财富文件,其次,应该表明,也等于ng-app指令,告诉应用它是基于angular的。第2,angular是透过种种吩咐来贯彻的,因而,第三个步骤就是读书种种指令。

下面代码中大家用到了一个ng-mode指令,l它将表单和模型联系在1块儿,可以在运用中‘眨眼间间’获得表单输入的内容。比如,上面包车型客车代码,你在表单中输入的始末会应声出现在hello的末端;而且,无论yourName变量何时产生转移它的具有引用也会立时更新。

二,加入1些决定

先是步,大家完成了一个简练的数码的双向绑定,不过,实际的应用场景中,情形比这纷纷的多,很所时候,大家须求收集,判断,处理等等。因而,大家需求参预壹些决定。

数量绑定:data-binding是壹种无论model哪天转移都会自动更新的格局,就像是上文讲到的‘须臾间’得到;同时,他也会在视图发生转移时更新model。这点让恼人的dom操作成了一件你不在需求操心的事。($scope.$apply();这段代码权且放在那里,它的作用之一正是足以流传model的转移,日常情状下,我们在页面中央直机关接参与的ng-model是足以“弹指间”更新的,不过只如若在jQuery的ajax中,并不是须臾间完成数据同步的,大家必要将改成传播出去,那样才能够起作用。可是,并不提倡滥用那几个法子,一般angular
JS自带的方法会暗中同意调用该措施。)

控制器:controller,权且叫它控制器吧,它是和dom成分相关的一名目繁多作为,它让您将这几个表现用干净可读性强的表单来表述,取代从前的样板式的经过挂号回调函数,只怕监听模型是不是爆发变动来更新form。

简短的原生JavaScript:分歧于别的框架,angular是简约的JavaScript项目,你不须要有专门的样子或许调用及后续来让您的东西匹配angular,那点让你的代码很简单测试,维护,重用,而且从犬牙相制的样板式调用中解放出来。

上面看三个方可添加未做事项清单的小应用;

html代码:

<!doctype html>
<html ng-app="todoApp">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" src="js/angular.min.js"></script>
        <script type="text/javascript" src="js/todo.js"></script>
        <style>
            .done-true {text-decoration: line-through;color: grey;}
            ul,li{list-style: none;}
        </style>
    </head>
    <body>
        <h2>需要做的事情清单</h2>
        <!--这个控制器内部的元素行为将被由ng-controller这个命令所指定的控制器TodoListController所控制。-->
        <div ng-controller="TodoListController as todoList">
            <!--{{todoList.todos.length}}{{todoList.todos.length}}数据调用-->
            您共有{{todoList.todos.length}}件需要做的事情,其中的{{todoList.todos.length}}项还未完成 [
            <!--ng-click="todoList.archive()"这也是一个方法调用,显示还未完成的清单列表-->
            <a href="" ng-click="todoList.archive()">仅显示未完成清单</a> ]
            <ul>
                <li ng-repeat="todo in todoList.todos">
                    <label class="checkbox">
                    <input type="checkbox" ng-model="todo.done">
                    {{todo.text}}
                  </label>
                </li>
            </ul>
            <!--调用方法ng-submit="todoList.addTodo()"-->
            <form ng-submit="todoList.addTodo()">
                <input type="text" ng-model="todoList.todoText" size="30" placeholder="添加你将要做的事情">
                <input class="btn-primary" type="submit" value="添加">
            </form>
        </div>
    </body>
</html>

 (1),ng-controller=”TodoListController as todoList”。

AngularJS,    注意那个as,后文大家调用TodoListController
时只须求选取todolist代替就好了,如:

      ng-submit=”todoList.addTodo()

 (2),ng-repeat=”todo in todoList.todos”。

    将 todoList.todos用todo来指代,后文可一贯todo.xxx的款式来调用todos里面的数据。

 (3), <span
class=”done-{{todo.done}}”>{{todo.text}}</span>。

    类名中一样能够选拔表明式,并且包蕴在双引号内部。

.done-true {
  text-decoration: line-through;
  color: grey;
}

 (4),ng-click=”todoList.archive()。

    事件调用。

瞩目看这一个措施,语法差不离正是JavaScript,只是有时加上了壹部分属于angular的法子。比如本例中的angular.forEach()。angular中得以一向使用JavaScript。

//定义控制器的方法archive,显示清单库中所有还未完成的事情。
        todoList.archive = function() {
            var oldTodos = todoList.todos;
            todoList.todos = [];
            angular.forEach(oldTodos, function(todo) {
                if(!todo.done) todoList.todos.push(todo);//如果事件未完成,则加入事件清单里面;
            });
        };

js代码:定义了二个模块todoApp,同时给那几个模块添加了一组数据和多个办法。

angular.module('todoApp', [])
    //所有的行为控制写在控制器里面;
    .controller('TodoListController', function() {
        var todoList = this;//定义当前控制器的对象;
        todoList.todos = [{//数据源
                text: '学习 AngularJS',
                done: true
            },
            {
                text: '建一个 AngularJS app',
                done: false
            }
        ];
        //定义控制器的方法addTodo,添加未完成的事情。
        todoList.addTodo = function() {
            todoList.todos.push({
                text: todoList.todoText,
                done: false
            });
            todoList.todoText = '';
        };
        //定义控制器的方法remaining,还未完成的事情数目
        todoList.remaining = function() {
            var count = 0;
            angular.forEach(todoList.todos, function(todo) {
                count += todo.done ? 0 : 1;
            });
            return count;
        };
        //定义控制器的方法archive,显示清单库中所有还未完成的事情。
        todoList.archive = function() {
            var oldTodos = todoList.todos;
            todoList.todos = [];
            angular.forEach(oldTodos, function(todo) {
                if(!todo.done) todoList.todos.push(todo);
            });
        };
    });

3,和后台交互

深链接(deep
link
):1个深链接,反应出用户此刻处在应用程式的尤其流程中,那对于用户将页面存为书签和发送邮件很有益,往返型的APP能够自行获得上述那个,不过ajax类型的接纳,则不或许落成那一个。angular
JS将深链接和桌面应用的类应用软件行为构成起来。

表单验证(Form
Validation
):客户端的表单验证是八个好的用户体验中很关键的三个版块。angularJS让你不用写JavaScript代码就足以证明证实规则。通过类名结合布尔值来判断,实现表单的验证。

服务端交互(Server Communication):angular
JS提供放置的劳动,这么些劳动基于XH奔驰M级和任何不少不及类型的第一方库提供的后台。promises能够很好地简化你的代码,通过管理异步的回调数据。下边包车型地铁例子,我们将经过AngularJS
的AngularFire 库来为二个简练的angular JS
应用软件搭建叁个Firebase后台。

先看代码:

主页面,首要加载能源文件和提供体现视图的容器,ng-view能够组合路由铺排完结同3个页面内部分歧子内容的加载。不一样的路由配置下,加载差异的模板。

<!doctype html>
<html ng-app="project">

    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="css/angular.css"/>
        <link rel="stylesheet" href="css/bootstrap.min.css" />
        <link rel="stylesheet" href="css/font-awesome.css" />
        <script type="text/javascript" src="js/jquery-1.9.1.min.js" ></script>
        <script type="text/javascript" src="js/bootstrap.min.js" ></script>
        <script type="text/javascript" src="js/angular.min.js" ></script>
        <script type="text/javascript" src="js/angular-resource.min.js" ></script>
        <script type="text/javascript" src="js/angular-route.min.js" ></script>
        <script src="https://cdn.firebase.com/js/client/2.0.4/firebase.js"></script>
        <script src="https://cdn.firebase.com/libs/angularfire/0.9.0/angularfire.min.js"></script>
        <script type="text/javascript" src="js/project.js" ></script>
        <script type="text/javascript" src="js/project-list.js" ></script>
    </head>
    <body>
        <div class="container">
            <h2>JavaScript Projects</h2>
            <!--我们通过这个div,作为加载局部页面或者视图的地方。它周围的页面会保持静态,
            当我们在这个模块中动态加载时,这样我们可以在一系列对象和表单之间切换,
            来添加新的项目或者编辑已经存在的项目。-->
            <!--动态加载不同的子内容,通过路由配置结合模板来实现,这之外的部分,保持静态-->
            <div ng-view></div>
        </div>
    </body>
</html>

列表模板:通过遍历取到的数据,生成列表。

<!--ng-model="projectList.search",将输入域和search属性绑定,这个选择器用来选择只包含用户输入的关键字的对象。-->
<input type="text" ng-model="projectList.search" class="search-query" id="projects_search" placeholder="Search">
<table>
    <thead>
        <!--表头-->
        <tr>
            <th>Project</th>
            <th>Description</th>
            <th>
                <!--一个连接到/new的路由,这个路由已经在project.js中配置过,
                既然我们遵循web的精神,没有必要在链接上注册回调函数,我们只是简单的导航到一个新的路由
                它会自动更新浏览器的浏览历史,并且使deep-linking可用。
                但是,不同于普通的server round trip application应用(服务器往返应用),这个navigation event会在浏览器中被立即渲染-->
                <a href="#!/new"><i class="icon-plus-sign"></i></a>
            </th>
        </tr>
    </thead>
    <!--表格主体-->
    <tbody>
        <!--ng-repeat="project in projectList.projects | filter:projectList.search | orderBy:'name'"
            ng-repeat用来展开一个数据集合,(遍历),对于集合中的每一条数据,angular都会执行一次生成操作
        -->
        <!--filter,用来选择一个集合的子集,该子集是包含projectList.search关键字的一个集合。
        orderBy,指定子集的排序规则-->
        <tr ng-repeat="project in projectList.projects | filter:projectList.search | orderBy:'name'">
            <!--遍历生成表格的每一行-->
            <td>
                <a ng-href="{{project.site}}" target="_blank">{{project.name}}</a>
            </td>
            <td>{{project.description}}</td>
            <td>
                <a ng-href="#!/edit/{{project.$id}}"><i class="icon-pencil"></i></a>
            </td>
        </tr>
    </tbody>
</table>

修改也许添加模板:重点是表单验证。

<!--创建一个名为myForm的表单,在这里我们会声明验证规则,来显示错误输入和不可操作的表单-->
<form name="myForm">
    <!--添加一个error类,当输入不合法时,$pristine意思是如果表单未被使用,也就是输入为空。-->
    <div class="control-group" ng-class="{error: myForm.name.$invalid && !myForm.name.$pristine}">
        <label>Name</label>
        <!--required:当没有输入时,将输入域置为无效-->
        <input type="text" name="name" ng-model="editProject.project.name" required>
            <!--show这个错误信息,当input name有requeired error时-->

        Required {{myForm.name.$pristine}}
    </div>

    <div class="control-group" ng-class="{error: myForm.site.$invalid && !myForm.site.$pristine}">
        <label>Website</label>
        <input type="url" name="site" ng-model="editProject.project.site" required>

        Required
        Not a URL
    </div>

    <label>Description</label>
    <textarea name="description" ng-model="editProject.project.description"></textarea>

    <br>
    <a href="#!/" class="btn">Cancel</a>
     <!--ng-disabled 将save按钮置为不可操作,当表单没有输入或者输入有误时-->
    <button ng-click="editProject.save()" ng-disabled="myForm.$invalid" class="btn btn-primary">Save</button>
    <button ng-click="editProject.destroy()" ng-show="editProject.project.$id" class="btn btn-danger">Delete</button>
</form>

JavaScript文件:

项目主代码:project.js。首要总结取多少,路由陈设和出示列表、添加档次、修改项目八个controller的定义。(注意里面包车型大巴各个注入的依赖,在function里面注脚)

//定义module,通过它你可以安装(加载)angular已有的服务和定义新的命令,服务和选择器等等。
angular.module('project', ['ngRoute', 'firebase'])
//模块可以依赖于其它模块,这里project需要firebase来处理这个应用的可持续。
    .value('fbURL', 'https://ng-projects-list.firebaseio.com/')
    //.value可以用来定义一个单独的对象,可以注入到其它的controllers和servises中去。前面是变量名,后面是值。
    .service('fbRef', function(fbURL) {
        return new Firebase(fbURL)//返回请求地址
    })
    .service('fbAuth', function($q, $firebase, $firebaseAuth, fbRef) {//$firebase firegase提供的一个服务
        var auth;
        return function() {
            if(auth) return $q.when(auth);
            var authObj = $firebaseAuth(fbRef);
            if(authObj.$getAuth()) {
                return $q.when(auth = authObj.$getAuth());
            }
            var deferred = $q.defer();
            authObj.$authAnonymously().then(function(authData) {
                auth = authData;
                deferred.resolve(authData);
            });
            return deferred.promise;
        }
    })
/**
 * Projects是firebase的一个实例,在project模块中已经定义过了,
 * 它提供对应用进行增加,删除和更新的方法(接口),
 * 它的目标是将服务器交互抽象化。
 * 它让controllers集中处理行为而不是复杂的服务器连接之类。
 **/
    .service('Projects', function($q, $firebase, fbRef, fbAuth, projectListValue) {
        var self = this;
        this.fetch = function() {//取数据,也就是和后台交互。这里是基于firebase,也可以是通过其他形式来进行数据调用,比如ajax
            if(this.projects) return $q.when(this.projects);
            return fbAuth().then(function(auth) {
                var deferred = $q.defer();
                var ref = fbRef.child('projects-fresh/' + auth.auth.uid);
                var $projects = $firebase(ref);
                ref.on('value', function(snapshot) {
                    if(snapshot.val() === null) {
                        //我们可以通过将一个对象的值设为null来删除它。
                        $projects.$set(projectListValue);
                    }
                    //$asArray()一个方法,以数组形式返回firebase里面的数据。
                    self.projects = $projects.$asArray();//取到数据并以数组形式返回
                    deferred.resolve(self.projects);
                });

                //Remove projects list when no longer needed.
                ref.onDisconnect().remove();
                return deferred.promise;
            });
        };
    })
    /* 
     * .config()可以用来对已经存在的服务进行配置,
     * 这里我们将对$routeProvider进行配置,来让它适用于局部路径。
     * */
    .config(function($routeProvider) {
        var resolveProjects = {
            projects: function(Projects) {
                return Projects.fetch();//获取数据,依赖于Projects模块
            }
        };

        $routeProvider
        /**
         * '/'当URL是/的时候,将会加载List.html到view里,同时和ProjectListController相关联,
         * 通过阅读路由定义,你可以立即得到一个关于APP结构的概览。
         * **/
            .when('/', {
                /**
                 * controller定义一个controller function可以和使用ng-congroller的dom元素关联
                 * 或者和一个view template通过在路由配置里面指定从而实现关联。
                 * **/
                controller: 'ProjectListController as projectList',//声明controller
                templateUrl: 'list.html',
                resolve: resolveProjects//数据调用
            })
            /**
             * '/edit/:projectId',这个路由定义我们使用了冒号,我们可以通过冒号来让URL的一个部分可以被controller调用。(类似于传参吧)
             * 现在,edit controller可以使用projectId作为参数,来找到需要edit的对象。
             * **/
            .when('/edit/:projectId', {
                controller: 'EditProjectController as editProject',
                templateUrl: 'detail.html',
                resolve: resolveProjects
            })
            .when('/new', {
                controller: 'NewProjectController as editProject',
                templateUrl: 'detail.html',
                resolve: resolveProjects
            })
            //.otherwise()指定,当当前路由不满足已经配置的所有路由时要显示的界面。
            .otherwise({
                redirectTo: '/'
            });
    })
//显示列表
    .controller('ProjectListController', function(projects) {
        var projectList = this;
        projectList.projects = projects;//把数据源导入
    })
//新增项目
    //可以通过$location服务,来使用浏览器的location对象
    .controller('NewProjectController', function($location, projects) {
        var editProject = this;
        //当视图中的save按钮被点击时,执行
        editProject.save = function() {
            projects.$add(editProject.project).then(function(data) {
                /**
                 * 我们用.path()方法来改变location的'deep-linking'location。
                 * URL的改变,会立即激活新的路由,并且让应用显示对应的view,这里也就是
                 * **/
                $location.path('/');//添加之后跳转到默认的列表页
            });
        };
    })
//修改项目
    .controller('EditProjectController',
    //$routeParams:这里我们让angular注入$routeParams,通过它来使从路由配置中提取出来的参数可用。
        function($location, $routeParams, projects) {
            var editProject = this;
            //projectId:提取URL中的projectId,它允许controller利用应用的deep-linking信息进行加工。(生成其它内容)
            var projectId = $routeParams.projectId,
                projectIndex;

            editProject.projects = projects;
            projectIndex = editProject.projects.$indexFor(projectId);
            editProject.project = editProject.projects[projectIndex];
            //当用户单击删除按钮时执行。
            editProject.destroy = function() {
                editProject.projects.$remove(editProject.project).then(function(data) {
                    $location.path('/');//删除之后跳转到主页。也就是默认的列表页
                });
            };

            editProject.save = function() {
                editProject.projects.$save(editProject.project).then(function(data) {
                    $location.path('/');//保存之后跳转到默认的列表页
                });
            };
        });

要点分析:

(一),angular.module:这么些讲话定义一个angular模块大概说是小的‘应用’,是二个针锋相对独立的单元,它能够有所本人的壹密密麻麻‘私有物’。

(二),angular.module.value:定义多少个独门的angular对象,他得以注入到任何的controllers可能service中去,作者的通晓是接近于js中的静态变量的觉得。

(3),angular.module.service:定义三个劳务,能够注入别的内容,在劳动中引用,本人也得以被引述。

(4),angular.module.factory:和service类似。

(5),angular.module.controller:定义controllers。

(陆),angular.module.config:用来对已经存在的劳务进行配置。

数码代码(模拟数据):project-list.js

angular.module('project').value('projectListValue', [{
        name: 'AngularJS',
        site: 'http://angularjs.org',
        description: 'HTML enhanced for web apps!'
    },
    {
        name: 'Angular',
        site: 'http://angular.io',
        description: 'One framework. Mobile and desktop.'
    },
    {
        name: 'jQuery',
        site: 'http://jquery.com/',
        description: 'Write less, do more.'
    },
    {
        name: 'Backbone',
        site: 'http://backbonejs.org/',
        description: 'Models for your apps.'
    },
    {
        name: 'SproutCore',
        site: 'http://sproutcore.com/',
        description: 'A Framework for Innovative web-apps.'
    },
    {
        name: 'Polymer',
        site: 'https://www.polymer-project.org/',
        description: 'Reusable components for the modern web.'
    },
    {
        name: 'Spine',
        site: 'http://spinejs.com/',
        description: 'Awesome MVC Apps.'
    },
    {
        name: 'Cappucino',
        site: 'http://www.cappuccino-project.org/',
        description: 'Objective-J.'
    },
    {
        name: 'Knockout',
        site: 'http://knockoutjs.com/',
        description: 'MVVM pattern.'
    },
    {
        name: 'GWT',
        site: 'http://www.gwtproject.org/',
        description: 'JS in Java.'
    },
    {
        name: 'Ember',
        site: 'http://emberjs.com/',
        description: 'Ambitious web apps.'
    },
    {
        name: 'React',
        site: 'https://facebook.github.io/react/',
        description: 'A JavaScript library for building user interfaces.'
    }
])

肆,创制组件

指令(Directives):指令是angular
JS中3个例外而又有力的特点,它让您成立新的html标签,只在你的使用范围内有效。

可选择组件(Reusable
Components):大家透过指令来创建可选择组件,组件让您可知隐藏复杂的dom结构,css和行为,它让你只关心应用做什么或许使用的外观中的三个下边。将两端分别来拍卖。

本地化(Localization):当地化是二个严厉或然说正式的APP中十三分关键的2个上面。angular
js的本地化感知过滤器和拦截指令给您独特的模块,让您的应用适用于拥有区域。

先看一个演示代码:

html:

<!DOCTYPE html>
<!--ng-app激活这个页面区域的APP 模块,这个模块包括BeerCounter controller,而且依赖于components module
它包含html扩展命令<tabs>和<pane>组件。-->
<html ng-app="app">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" href="../backend/css/bootstrap.min.css" />
        <link rel="stylesheet" href="../backend/css/font-awesome.css" />
        <script type="text/javascript" src="../backend/js/jquery-1.9.1.min.js" ></script>
        <script type="text/javascript" src="../backend/js/bootstrap.min.js" ></script>
        <script type="text/javascript" src="../js/angular.min.js" ></script>
        <script src="components.js"></script>
        <script src="app.js"></script>
    </head>

    <body class="container">
        <!--我们通过普通的tabs扩展了html的标签库,它抽象了渲染tabs所需要的复杂的html结构和相关行为,
        生成一个可读性强的视图,同时也是一个可重用的序列。-->
        <tabs>
            <!--组件可以以html属性的形式携带参数,在这里,title属性指定了tabs的文本;
                Localization一个演示angular中num,data等的数据格式和本地化;
                两个pane分别代表两个tab切换卡的内容。一个标题为Localization,另一个标题为Pluralization
            -->
            <pane title="Localization">
                Date: {{ '2012-04-01' | date:'fullDate' }}<br>
                Currency: {{ 123456 | currency }}<br>
                Number: {{ 98765.4321 | number }}<br>
            </pane>
            <!--Pluralization一个演示angular多元化的例子,注意数量改变时,beer的不同形式。-->
            <pane title="Pluralization">
                <!--我们通过BeerCounter controller来建立基于本地的计数规则-->
                <div ng-controller="BeerCounter">
                    <div ng-repeat="beerCount in beers">
                        <!--ng-pluralize指令为每个区域选择正确的显示格式,不同于英语,其它语言通常都有基于包含项目数组的复杂的显示规则
                        count="beerCount",绑定到number属性,它成为选择显示格式的选择器
                        when="beerForms"绑定到多元化规则,这些规则会因为语言个地区的不同组合而不同。-->
                        <ng-pluralize count="beerCount" when="beerForms"></ng-pluralize>
                    </div>
                </div>
            </pane>
        </tabs>
    </body>

</html>

去掉注释和引用后的重头戏html代码:

<body class="container">
        <tabs>
            <pane title="Localization">
                Date: {{ '2012-04-01' | date:'fullDate' }}<br>
                Currency: {{ 123456 | currency }}<br>
                Number: {{ 98765.4321 | number }}<br>
            </pane>
            <pane title="Pluralization">
                <div ng-controller="BeerCounter">
                    <div ng-repeat="beerCount in beers">
                        <ng-pluralize count="beerCount" when="beerForms"></ng-pluralize>
                    </div>
                </div>
            </pane>
        </tabs>
    </body>

html中1度开端化了采取,那里差不多分析下那段代码:那段代码应用了多个自定义标签,tabs和pane。tabs是我们普遍的切换卡,代码中通过pane的title属性将自个儿和tabs标题关联起来。title的值便是它所对应的tabs的标题。所以,简要抽象那些组件的话可以看成上面的始末:

<tabs>
    <pane title='我是选项卡标题'>
          <div>我是选项卡内容</div>
    </pane>
    <pane title='标题1'>
          <div>我是选项卡内容</div>
    </pane>
    <pane title='标题2'>
         <div>我是选项卡内容</div>
    </pane>
</tabs>

JavaScript:

components.js

这几个文件中定义了八个零部件,tabs和pane。pane包蕴在tabs之中。pane之中调用了tabs的controller,所以能够在里头调用它的不2秘诀,即addPane();

angular.module('components', [])
//通过module的.directive()方法来为我们的应用定义新的标签,比如这里定义了tabs标签,
    .directive('tabs', function() {
        return {
            //restrict定义html形式,是E的话,组件只能是el形式
            restrict: 'E',
//            指定当angular使用扩展的标签替换tabs时它应该将原始内容放置于由ng-transclude指令指定的位置.
            transclude: true,
//            组件需要私有的scope,以便它的视图属性不会突然在tabs之外被修改,
//            如果你确实需要暴露内容,你可以声明input/output 的内容,这一点可以参考后文的pans的定义
            scope: {},
//            和应用一样,组件也可以拥有一个controllers,来提供组件的行为,$scope为组件的scope, $element为组件所在的元素
            controller: function($scope, $element) {
//                $scope组件的scope
//                $element要放置组件的元素,调用组件时传入。
                var panes = $scope.panes = [];
//                发布一个select()方法,用来在tab之间切换视图。
                $scope.select = function(pane) {
                    angular.forEach(panes, function(pane) {
                        pane.selected = false;//通过布尔值控制是否被选中。这里是将所有的pane都设为非选中状态
                    });
                    pane.selected = true;//当前传入的这个设为选中状态
                }
//                组件通常需要结合在一起,形成一个单元,在这里,我们的pane标签,将通过addPane()方法,将自己注册到它的容器<tabs>里面。
                this.addPane = function(pane) {
                    if(panes.length == 0) $scope.select(pane);
                    panes.push(pane);
                }
            },
//            将被浏览器渲染替换tabs里面的内容,注意,模板内部也可以使用指令
            template: '<div class="tabbable">' +
                '<ul class="nav nav-tabs">' +
//                ng-class="{active:pane.selected}"我们创建active类名,来为处于激活状态的tab设置样式。
                '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">' +
                '<a href="" ng-click="select(pane)">{{pane.title}}</a>' +
                '</li>' +
                '</ul>' +
//                ng-transclude标记tabs的内容将会放置在哪里
                '<div class="tab-content" ng-transclude></div>' +
                '</div>',
//                replace: true告诉angular tabs将会被模板替换,而不是放在它之后
            replace: true
        };
    })

    .directive('pane', function() {
        return {
//            require: '^tabs',说明pane组件必须在tabs组件的内部,这让pane组件能够使用tabs组件的方法,在这里也就是addPane();
            require: '^tabs',
            restrict: 'E',
            transclude: true,
            scope: {
                title: '@'
            },
            link: function(scope, element, attrs, tabsController) {
//            tabsController.addPane(scope);我们之前说过,我们需要tabs作为我们的容器,这里我们传递它的实例
                tabsController.addPane(scope);
            },
            template: '<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' +
                '</div>',//将替换pane标签的内容
            replace: true
        };
    })

app.js

 那是app模块的概念,那里注入了对于components的依靠,那就确认保证了笔者们能够在利用中选拔本身定义的授命;同时,那一个文件中也定义了多元化规则,比如,是塞尔维亚(Serbia)语时如何体现,其余语言时又如何体现。

//app模块声明了一个对components模块的依赖,这确保了components模块中的指令,同时也会被加载到应用中.
angular.module('app', ['components'])
//$locale服务包含了一系列和本地化相关的内容,是每一种语言,本地化的混合体.
    .controller('BeerCounter', function($scope, $locale) {
//设置beers的计数数组,我们将会迭代这个数组,然后看beers的变化情况,也就是本地化
        $scope.beers = [0, 1, 2, 3, 4, 5, 6];
//$locale.id == 'en-us':基于本地情况创建不同的多元化规则,在真实的应用中,我们会加载包含每种语言本地化和相关规则的模块。
        if($locale.id == 'en-us') {
            //$scope.beerForms 适应于英语的多元化规则。
            $scope.beerForms = {
                0: 'no beers',
                one: '{} beer',
                other: '{} beers'
            };
        } else {
            $scope.beerForms = {
                0: 'žiadne pivo',
                one: '{} pivo',
                few: '{} pivá',
                other: '{} pív'
            };
        }
    });

小结:那篇小说基于angular官方文书档案,从angular的底蕴,参预一些控制,和后台交互以及开创组件三个方面粗略的介绍了angular。意在对angular有一个从头的可比完美的认识。因为刚起先接触,说的或是有点片面,也不能够很好的做贰个系统的总括,中期再渐渐补充,不足之处,欢迎提议!

相关文章