前言:记得三月份时下定决心说天天要更新一篇博客,学习点新东西,实践下来发现太不现实,生活中的事情不少,再喜欢也不能让它一件占据生活的所有吧,因此呢,之后顺其天然吧。以前有一篇‘初识angular’由于离职找工做等一系列缘由,搁置了很久,今早看看,继续写之前的已经没法继续,索性从新开始,有时间再修该以前的吧。javascript
地址:https://angularjs.org/css
一,基础:先看html代码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的。第三,angular是经过各类指令来实现的,所以,第三个步骤就是学习各类指令。java
上面代码中咱们用到了一个ng-mode指令,l它将表单和模型联系在一块儿,可以在应用中‘瞬间’得到表单输入的内容。好比,上面的代码,你在表单中输入的内容会马上出如今hello的后面;并且,不管yourName变量什么时候发生改变它的全部引用也会当即更新。react
二,加入一些控制jquery
第一步,咱们实现了一个简单的数据的双向绑定,可是,实际的应用场景中,状况比这复杂的多,很所时候,咱们须要收集,判断,处理等等。所以,咱们须要加入一些控制。git
数据绑定:data-binding是一种不管model什么时候改变都会自动更新的方式,就如上文讲到的‘瞬间’得到;同时,他也会在视图发生改变时更新model。这一点让烦人的dom操做成了一件你不在须要担忧的事。($scope.$apply();这段代码暂且放在这里,它的做用之一就是能够传播model的变化,一般状况下,咱们在页面中直接加入的ng-model是能够“瞬间”更新的,可是若是是在jQuery的ajax中,并非瞬间实现数据同步的,咱们须要将改变传播出去,这样才能够起做用。可是,并不提倡滥用这个方法,通常angular JS自带的方法会默认调用该方法。)angularjs
控制器:controller,暂且叫它控制器吧,它是和dom元素相关的一系列行为,它让你将这些行为用干净可读性强的表单来表达,取代之前的样板式的经过注册回调函数,或者监听模型是否发生改变来更新form。github
简单的原生JavaScript:不一样于其余框架,angular是简单的JavaScript项目,你不须要有专门的样板或者调用及继承来让你的东西匹配angular,这一点让你的代码很容易测试,维护,重用,并且从复杂的样板式调用中解放出来。web
下面看一个能够添加未作事项清单的小应用;
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}}数据调用--> <span>您共有{{todoList.todos.length}}件须要作的事情,其中的{{todoList.todos.length}}项还未完成</span> [ <!--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"> <span class="done-{{todo.done}}">{{todo.text}}</span> </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"。
注意这个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); }); }; });
三,和后台交互
深连接(deep link):一个深连接,反应出用户此刻处在APP的那个流程中,这对于用户将页面存为书签和发送邮件很方便,往返型的APP能够自动得到以上这些,可是ajax类型的应用,则不可能实现这些。angular JS将深连接和桌面应用的类APP行为结合起来。
表单验证(Form Validation):客户端的表单验证是一个好的用户体验中很重要的一个版块。angularJS让你不用写JavaScript代码就能够声明验证规则。经过类名结合布尔值来判断,实现表单的验证。
服务端交互(Server Communication):angular JS提供嵌入的服务,这些服务基于XHR和其余不少不一样种类的第三方库提供的后台。promises可以很好地简化你的代码,经过管理异步的回调数据。下面的例子,咱们将经过AngularJS 的AngularFire 库来为一个简单的angular JS APP搭建一个Firebase后台。
先看代码:
主页面,主要加载资源文件和提供显示视图的容器,ng-view能够结合路由配置实现同一个页面内部不一样子内容的加载。不一样的路由配置下,加载不一样的模板。
<!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时--> <span ng-show="myForm.name.$error.required && !myForm.name.$pristine" class="help-inline"> Required {{myForm.name.$pristine}}</span> </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> <span ng-show="myForm.site.$error.required && !myForm.site.$pristine" class="help-inline"> Required</span> <span ng-show="myForm.site.$error.url" class="help-inline">Not a URL</span> </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('/');//保存以后跳转到默认的列表页 }); }; });
要点分析:
(1),angular.module:这个语句定义一个angular模块或者说是小的‘应用’,是一个相对独立的单元,它能够拥有本身的一系列‘私有物’。
(2),angular.module.value:定义一个独立的angular对象,他能够注入到其它的controllers或者service中去,个人理解是相似于js中的静态变量的感受。
(3),angular.module.service:定义一个服务,能够注入其它内容,在服务中引用,自己也能够被引用。
(4),angular.module.factory:和service相似。
(5),angular.module.controller:定义controllers。
(6),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中一个独特而又强大的特色,它让你建立新的html标签,只在你的应用范围内有效。
可重用组件(Reusable Components):咱们经过指令来建立可重用组件,组件让你可以隐藏复杂的dom结构,css和行为,它让你只关注应用作什么或者应用的外观中的一个方面。将二者分开来处理。
本地化(Localization):本地化是一个严谨或者说正式的APP中很是重要的一个方面。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"> <span>Date: {{ '2012-04-01' | date:'fullDate' }}</span><br> <span>Currency: {{ 123456 | currency }}</span><br> <span>Number: {{ 98765.4321 | number }}</span><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"> <span>Date: {{ '2012-04-01' | date:'fullDate' }}</span><br> <span>Currency: {{ 123456 | currency }}</span><br> <span>Number: {{ 98765.4321 | number }}</span><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中已经初始化了应用,这里简要分析下这段代码:这段代码用到了两个自定义标签,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,因此能够在内部调用它的方法,即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的依赖,这就保证了咱们能够在应用中使用本身定义的指令;同时,这个文件中也定义了多元化规则,好比,是英语时如何显示,其它语言时又如何显示。
//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有一个初步的比较全面的认识。由于刚开始接触,说的可能有点片面,也不能很好的作一个系统的总结,后期再慢慢补充,不足之处,欢迎提出!