AngularJS 开始入门 关于 AngularJS AngularJS 必要准备工作 快速入门 为什么要用AngularJS? HTML非常适合于声明静态的文档,但是当我们试图使用它在web应用程序中声明动态视图时,它显得力不从心。AngularJS能为您的应用程序扩展HTML的词汇。由此产生的环境非常具有有表现力、可读性强、快速发展。 替代选择 其他处理HTML的缺点的框架要么是抽象出HTML、CSS、和/或JavaScript,要么为操纵DOM提供一个必要的方式。它们都不能解决一个根本问题,即HTML不是为动态视图设计的。 可扩展性 AngularJS是用来构建框架的工具集,很适全于你的应用程序开发。它完全可扩展,而且与别的库协作得很好。每个功能可以被修改或替代,以适合你的独一无二的开发工作流以及功能需要。继续阅读以弄懂为何。 The Basics index.html <!doctype html> <html ng-app> <head> <script src="//img.CodingDict/attachments/image/wk/angularjs/angular.min.js"></script> </head> <body> <div> <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <h1>Hello {{yourName}}!</h1> </div> </body> </html> 添加一些控件 数据绑定 数据绑定是每当模型改变时更新视图的自动方法,当视图改变时,同样也会更新模型。这非常棒,因为从你需要担心的列表中它减去了DOM操纵。 控件 控件是DOM元素后面的行为。AngularJS让你能够用一个干净可读的形式表达行为,不需要更新DOM的通常样板、注册回调或者观察模型变化。 扁平的JavaScript 与别的框架不同,不需要为包装访问器方法中的模型,而继承私有类型。Angular模型是扁平的旧式JavaScript对象。这使你的代码容易读取、容易维护、可重用,还不需要样板。 index.html <!doctype html> <html ng-app="todoApp"> <head> <script src="//img.CodingDict/attachments/image/wk/angularjs/angular.min.js"></script> <script src="todo.js"></script> <link rel="stylesheet" href="todo.css"> </head> <body> <h2>Todo</h2> <div ng-controller="TodoListController as todoList"> <span>{{todoList.remaining()}} of {{todoList.todos.length}} remaining</span> [ <a href="" ng-click="todoList.archive()">archive</a> ] <ul class="unstyled"> <li ng-repeat="todo in todoList.todos"> <input type="checkbox" ng-model="todo.done"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li> </ul> <form ng-submit="todoList.addTodo()"> <input type="text" ng-model="todoList.todoText" size="30" placeholder="add new todo here"> <input class="btn-primary" type="submit" value="add"> </form> </div> </body> </html> todo.js angular.module('todoApp', []) .controller('TodoListController', function() { var todoList = this; todoList.todos = [ {text:'learn angular', done:true}, {text:'build an angular app', done:false}]; todoList.addTodo = function() { todoList.todos.push({text:todoList.todoText, done:false}); todoList.todoText = ''; }; todoList.remaining = function() { var count = 0; angular.forEach(todoList.todos, function(todo) { count += todo.done ? 0 : 1; }); return count; }; todoList.archive = function() { var oldTodos = todoList.todos; todoList.todos = []; angular.forEach(oldTodos, function(todo) { if (!todo.done) todoList.todos.push(todo); }); }; }); todo.css .done-true { text-decoration: line-through; color: grey; } 后端连接 深链接 一个深链接反应了用户在应用中的哪个位置,这很有用,所以用户可以把它存为书签以及电子邮件链接,以在应用内部定位它。往返旅行的应用程序会自动获得这个功能,但Ajax应用程序按其性质不会。AngularJS结合了深链接以及类似桌面应用程序的行为的优点。 表单验证 客户端表单验证是完美的用户体验的一个重要的部分。AngularJS使你能够声明表单的有效性规则,而不需要书写JavaScript代码。从而事半功倍。 服务器通信 AngularJS提供了内建的建在在XHR的顶层的服务,以及多种多样的使用第三方库的其它后端。通过处理异步返回的数据,Promise进一步简化了您的代码。在这个示例中,我们使用AngularFire库以把一个Firebase后端接通到一个简单的Angular应用上。 index.html <!doctype html> <html ng-app="project"> <head> <script src="/attachments/image/wk/angularjs/angular.min.js"></script> <script src="/attachments/image/wk/angularjs/angular-resource.min.js"> </script> <script src="/attachments/image/wk/angularjs/angular-route.min.js"> </script> <script src="/attachments/image/wk/angularjs/firebase.js"></script> <script src="/attachments/image/wk/angularjs/angularfire.min.js"></script> <link rel="stylesheet" href="bootstrap.css"> <script src="project.js"></script> </head> <body> <h2>JavaScript Projects</h2> <div ng-view></div> </body> </html> bootstrap.css // Uncomment this in Plunker or JSFiddle: @import '//netdna.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css'; project.js angular.module('project', ['ngRoute', 'firebase']) .value('fbURL', 'https://ng-projects-list.firebaseio.com/') .service('fbRef', function(fbURL) { return new Firebase(fbURL) }) .service('fbAuth', function($q, $firebase, $firebaseAuth, fbRef) { 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; } }) .service('Projects', function($q, $firebase, fbRef, fbAuth) { var self = this; this.fetch = function () { 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) { $projects.$set(window.projectsArray); } self.projects = $projects.$asArray(); deferred.resolve(self.projects); }); //Remove projects list when no longer needed. ref.onDisconnect().remove(); return deferred.promise; }); }; }) .config(function($routeProvider) { var resolveProjects = { projects: function (Projects) { return Projects.fetch(); } }; $routeProvider .when('/', { controller:'ProjectListController as projectList', templateUrl:'list.html', resolve: resolveProjects }) .when('/edit/:projectId', { controller:'EditProjectController as editProject', templateUrl:'detail.html', resolve: resolveProjects }) .when('/new', { controller:'NewProjectController as editProject', templateUrl:'detail.html', resolve: resolveProjects }) .otherwise({ redirectTo:'/' }); }) .controller('ProjectListController', function(projects) { var projectList = this; projectList.projects = projects; }) .controller('NewProjectController', function($location, projects) { var editProject = this; editProject.save = function() { projects.$add(editProject.project).then(function(data) { $location.path('/'); }); }; }) .controller('EditProjectController', function($location, $routeParams, projects) { var editProject = this; 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('/'); }); }; }); list.html <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><a href="#/new"><i class="icon-plus-sign"></i></a></th> </tr> </thead> <tbody> <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> detail.html <form name="myForm"> <div class="control-group" ng-class="{error: myForm.name.$invalid && !myForm.name.$pristine}"> <label>Name</label> <input type="text" name="name" ng-model="editProject.project.name" required> <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> <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> 创建组件 指令 指令是一个独有而且强大的功能,只在Angular中可用。指令使你能够发明新的HTML句法、专针对于你的应用程序。 可重用的组件 我们使用指令以创建可重复使用的组件。组件允许你隐藏复杂的DOM结构、CSS以及行为。这使你能够专注于应用程序要做什么,或者单独的应用程序看起来如何。 本地化 严肃的应用程序的一个重要组成部分是本地化。AngularJS的本地探知筛选器以及阻塞指令使你能够建立屏蔽,使你的应用程序在所有的地方都可用。 index.html <!doctype html> <html ng-app="app"> <head> <script src="//img.CodingDict/attachments/image/wk/angularjs/angular.min.js"></script> <script src="components.js"></script> <script src="app.js"></script> <link rel="stylesheet" href="bootstrap.css"> </head> <body> <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> components.js angular.module('components', []) .directive('tabs', function() { return { restrict: 'E', transclude: true, scope: {}, controller: function($scope, $element) { var panes = $scope.panes = []; $scope.select = function(pane) { angular.forEach(panes, function(pane) { pane.selected = false; }); pane.selected = true; } this.addPane = function(pane) { if (panes.length == 0) $scope.select(pane); panes.push(pane); } }, template: '<div class="tabbable">' + '<ul class="nav nav-tabs">' + '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+ '<a href="" ng-click="select(pane)">{{pane.title}}</a>' + '</li>' + '</ul>' + '<div class="tab-content" ng-transclude></div>' + '</div>', replace: true }; }) .directive('pane', function() { return { require: '^tabs', restrict: 'E', transclude: true, scope: { title: '@' }, link: function(scope, element, attrs, tabsController) { tabsController.addPane(scope); }, template: '<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' + '</div>', replace: true }; }) app.js angular.module('app', ['components']) .controller('BeerCounter', function($scope, $locale) { $scope.beers = [0, 1, 2, 3, 4, 5, 6]; if ($locale.id == 'en-us') { $scope.beerForms = { 0: 'no beers', one: '{} beer', other: '{} beers' }; } else { $scope.beerForms = { 0: '?iadne pivo', one: '{} pivo', few: '{} pivá', other: '{} pív' }; } }); bootstrap.css // Uncomment this in Plunker or JSFiddle: @import '//netdna.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css'; 可测性内置 可注入 在AngularJS依赖性注入允许你声明式地描述你的应用程序是如何连线的。这意味着你的应用程序不需要main()方法,该方法通常是一个难以维护的大堆杂。依赖性的注入也是AngularJS的一个核心。这意味着任何不适合你的需要的组件可以轻松替换掉。 可测试 AngularJS设计为从根基开始都是可测试的。它鼓励行为与视图分离、用预绑定来模拟、充分利用依赖性注入。它还配备了端到端的场景分流道,它通过理解AngularJS的内部运作机制消除了测试片层分享。 关于 AngularJS AngularJS 必要准备工作