初识Angular
简介AngularJS是一款前端MVC框架,是以数据和逻辑为驱动核心的框架,最为核心的是:模块化、数据双向绑定、依赖注入。 var App=angular.module('App',[]); App.controller('AppController',['$scope',function($scope){ $scope.say='Hello World'; }]) MVCMVC是一种开发模式,由模型(Model)、视图(View)、控制器(Controller)3部分构成,采用这种开发模式为合理组织代码提供了方便、降低了代码间的耦合度、功能结构清晰可见。
模块化使用AngularJS构建应用(App)时是以模块化(Module)的方式组织的,即将整个应用划分成若干模块,每个模块都有各自的职责,最终组合成一个整体。 定义应用通过为任何一个HTML标签添加ng-app属性,可以指定一个应用,表示此标签所包裹的内容都属于应用(App)的一部分。 <html ng-app="App"> </html>
定义模块AngularJS提供了一个 //通过module方法定义模块,应用app本质也是一个模块 //module方法需要两个参数 //参数一:模块的名称 //参数二:需要依赖的模块 var app = angular.module('app',[]); 定义控制器控制器(Controller)作为连接模型(Model)和视图(View)的桥梁存在,所以当我们定义好了控制器以后也就定义好了模型和视图。 // app是一个实例模块对象 // 通过这个实例对象可以创建控制器 // controller有两个参数 // 参数1:控制器名称 // 参数2:是一个数组,除最后一个是函数外,其他的都是字符串,表明控制器的依赖关系 app.controller('appController',function($scope){ $scope.people = [{'name':'ZS','age':55}] }]) 模型(Model)数据是要展示到视图(View)上的,所以需要将控制器(Controller)关联到视图(View)上,通过为HTML标签添加 <!-- 添加ng-controller属性,并赋值为相应的控制器名称 --> <table ng-controller="appController"> <tr> <th>姓名</th> <th>年龄</th> </tr> <tr> <td>{{people.name}}</td> <td>{{people.age}}</td> </tr> </table> 指令HTML在构建应用(App)时存在诸多不足之处,AngularJS通过扩展一系列的HTML属性或标签来弥补这些缺陷,所谓指令就是AngularJS自定义的HTML属性或标签,这些指令都是以 内置指令
自定义指令AngularJS允许根据实际业务需要自定义指令,通过angular全局对象下的directive方法实现。 //指令的生命周期开始于 $compile 方法并结束于 link 方法 //自定义指令的全部可设置的属性大致如下 //指令的选项如下所示,每个键的值说明了可以将这个属性设置为何种类型或者什么样的函数: angular.module('myApp',[]) .directive('myDirective',function() { //指令名称myDirective return { //返回一个对象 restrict: String,//可选字符串参数,可以设置这个指令在DOM中可以何种形式被声明, //默认为A(attr(当做标签属性来使用))<div my-directive></div> // 设置为“E”(ele,(直接当做标签来使用)) <my-directive></my-directive> //C(类名) //<div class="my-directive:expression;"></div> //M(注释) //<--directive:my-directive expression--> //这些选项可以单独使用,也可以混合在一起使用: //angular.module('myDirective',function(){ // return { // restrict: 'EA' // 输入元素或属性 // }; //}) priority: Number,//优先级,可忽略,默认为0, ngRepeat的优先级为1000,这样就可以保证在同一元素上,它总是在其他指令之前被调用。 terminal: Boolean,//(布尔型),true或false,如果为false,则这个参数用来告诉AngularJS停止运行当前元素上比本指令优先级低的指令。优先级相同的指令还是会被执行。 ngIf 的优先级略高于 ngView , template: String or Template Function: //(字符串或函数)指令中的一个重要的一个属性,必须被设置其中一种 //1, 一段HTML文本; //2,可以接收两个参数的函数,参数为 tElement 和 tAttrs //在html模板中必须只有一个根html标签,且如果有换行则需要使用“” //例如template: ' // <div> <-- single root element --> // <a href="http://google.com">Click me</a> // <h1>When using two elements,wrap them in a parent element</h1> // </div> //function(tElement,tAttrs) (...},//更好的选择是使用 templateUrl 参数引用外部模板,参考下面的参数 templateUrl: String,//(字符串或函数)1,外部路径的字符串,2,接受两个参数的函数,参数为 tElement 和 tAttrs ,并返回一个外部HTML文件路径的字符串 //模板加载后,AngularJS会将它默认缓存到 $templateCache 服务中。(可以提前加载模块到缓存中,提高加载速度) replace: Boolean or String,//(布尔型)默认为false(模板内容会加载到标签内部),true(模板内容会替换当前标签) scope: Boolean or Object,//(布尔型或对象),默认为false,设置为true 时,会从父作用域继承并创建一个新的作用域对象。 // ng-controller 的作用,就是从父级作用域继承并创建一个新的子作用域。 //如果要创建一个能够从外部原型继承作用域的指令,将 scope 属性设置为 true //设置为一个对象,则能设置 隔离作用域, scope 属性设置为一个空对象 {} 。如果这样做了,指令的模板就无法访问外部作用域了: //例如.directive('myDirective',function() { // return { // restrict: 'A',// scope: {},// priority: 100,// template: '<div>Inside myDirective {{ myProperty }}</div>' // }; // }); //在scope对象中,还可以使用“@” “=” “&”,来设置模板中数据的作用域和绑定规则 //"@" 本地作用域属性:使用当前指令中的数据和DOM属性的值进行绑定 //“=” 双向绑定:本地作用域上的属性同父级作用域上的属性进行双向的数据绑定。 //“&” 父级作用域绑定:通过 & 符号可以对父级作用域进行绑定 //例如 //scope: { // ngModel: '=',// 将ngModel同指定对象绑定 // onSend: '&',// 将引用传递给这个方法 // fromName: '@' // 储存与fromName相关联的字符串 //} transclude: Boolean,//默认为false.只有当你希望创建一个可以包含任意内容的指令时, 才使用 transclude: true 。 //如果指令使用了 transclude 参数,那么在控制器(下面马上会介绍)中就无法正常监听数 //据模型的变化了。 controller: String or function(scope,element,attrs,transclude,otherInjectables) { ... },//(字符串或函数)注册在应用中的控制器的构造函数 //使用函数创建内联控制器,例如 //angular.module('myApp',[]) // .directive('myDirective',function() { // restrict: 'A',// controller: / function($scope,$element,$attrs,$transclude) { // // 控制器逻辑放在这里 // } //}) controllerAs: String,//可以在指令中创建匿名控制器,例如 //.directive('myDirective',function() { // return { // restrict: 'A',// template: '<h4>{{ myController.msg }}</h4>',// controllerAs: 'myController',// controller: function() { // this.msg = "Hello World" // } // }; //}); require: String,//(字符串或数组)字符串代表另外一个指令的名字,如果没有前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器(或 //具有指定名字的指令)就抛出一个错误。 //例如 //如果不使用 ^ 前缀,指令只会在自身的元素上查找控制器。 //require: 'ngModel' // 使用 ? 如果在当前指令中没有找到所需要的控制器,会将 null 作为传给 link 函数的第四个参数 //require: '?ngModel' //使用 ^ 如果添加了 ^ 前缀,指令会在上游的指令链中查找 require 参数所指定的控制器。 //require: '^ngModel' // 使用 ^? 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找。 //require: '^?ngModel',link: function(scope,iElement,iAttrs) { ... },//compile 选项本身并不会被频繁使用,但是 link 函数则会被经常使用。 //当我们设置了 link 选项, 实际上是创建了一个 postLink() 链接函数, 以便 compile() 函数可以定义链接函数。 //compile 和 link 选项是互斥的。如果同时设置了这两个选项,那么会把 compile //所返回的函数当作链接函数,而 link 选项本身则会被忽略。 //通常情况下,如果设置了 compile 函数,说明我们希望在指令和实时数据被放到DOM中之前 //进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。 //用 link 函数创建可以操作DOM的指令。 //require 'SomeController',//link: function(scope,SomeController) { // 在这里操作DOM,可以访问required指定的控制器 //} compile: function(tElement,tAttrs,transclude) { return { pre: function(scope,iAttrs,controller) { ... },post: function(scope,controller) { ... } } // 或者 return function postLink(...) { ... } } }; }); 数据绑定AngularJS是以数据做为驱动的MVC框架,所有模型(Model)里的数据经由控制器(Controller)展示到视图(View)中。 所谓数据绑定指的就是将模型(Model)中的数据与相应的视图(View)进行关联,分为单向绑定和双向绑定两种方式。 单项绑定单向数据绑定是指将模型(Model)数据,按着写好的视图(View)模板生成HTML标签,然后追加到DOM中显示,如 双向绑定双向绑定则可以实现模型(Model)数据和视图(View)模板的双向传递。 相关指令在AngularJS中通过 注: 通过为表单元素添加 通过 AngularJS对事件也进行了扩展,无需显式的获取DOM元素便可以添加事件,易用性变的更强。通过在原有事件名称基础上添加 通过 作用域通常AngularJS中应用(App)是由若干个视图(View)组合成而成的,而视图(View)又都是HTML元素,并且HTML元素是可以互相嵌套的,另一方面视图都隶属于某个控制器(Controller),进而控制器之间也必然会产生嵌套关系。 每个控制器(Controller)又都对应一个模型(Model)也就是 根作用域一个AngularJS的应用(App)在启动时会自动创建一个根作用域 <!-- 指定一个div为应用的根元素,这个div根元素对应的便是$rootScope --> <!-- 通过ng-init为$rootScope添加数据 --> <div ng-app="App" ng-init="name='ZS'"> <span>{{name}}</span> </div> 子作用域通过 过滤器在AngularJS中使用过滤器格式化展示数据,在 内置过滤器
自定义过滤器通过模块对象实例提供的 <!DOCTYPE html> <html ng-app="App"> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div ng-controller="DemoController"> {{content|uppercase}} </div> <script type="text/javascript"> var App = angular.module('App',[]); App.controller('DemoController',function($scope){ $scope.content = 'my name is Hanmeimei'; }]) // 自定义过滤器 App.filter('upperCase',function () { return function (info) { return info[0].toUpperCase() + info.slice(1); } }) </script> </body> </html> 依赖注入AngularJS采用模块化的方式组织代码,将一些通用逻辑封装成一个对象或函数,实现最大程度的复用,这导致了使用者和被使用者之间存在依赖关系。 所谓依赖注入是指在运行时自动查找依赖关系,然后将查找到依赖传递给使用者的一种机制。 常见的AngularJS内置服务有 推断式注入没有明确声明依赖,AngularJS会将函数参数名称当成是依赖的名称。 // 控制器依赖$scope和$http模块 // 但并没有申明依赖,这时候会自动将函数中的参数当做依赖对待 App.controller('DemoController',function($scope,$http){ // 发送ajax请求 $http({ method:'GET',url:'xxx.php',}); })
行内注入以数组形式明确声明依赖,数组元素都是包含依赖名称的字符串,数组最后一个元素是依赖注入的目标函数。 App.controller('DemoController','$http','$filter',$http,$filter){ // 发送ajax请求 $http({ method:'POST',}); }]) 服务服务是一个对象或函数,对外提供特定的功能。 内建服务(内置服务)
App.controller('DemoController','$location',$loaction){ $location.absUrl(); // 绝对路径 $location.protocol(); // 协议 $location.port(); // 端口 $location.path(); // 当前路径 $location.hash(); // 哈希值 $location.search(); // 查询字符串 }])
App.controller('DemoController',['$timeout','$interval','$scope',function($timeout,$interval,$scope){ $timeout(function(){ $scope.time = new Date(); },2000); $interval(function(){ $scope.time = new Date(); },1000) }])
App.controller('DemoController',$filter){ // 初始内容 $scope.content = '100'; // 创建过滤器 var currency = $filter('currency'); // 格式化数据 $scope.content = currency($scope.content); }])
App.controller('DemoController',['$log',function($log){ $log.log('日志'); $log.info('信息'); $log.warn('警告'); $log.error('错误'); $log.debug('调试'); }])
App.controller('DemoController',// 请求方式 url:'xxx.php',// 请求页面 data:{ // 请求主体 name:'ZS',age:18 },param:{ // 以?key1=value1&key2=value2这种格式将参数拼接到url后面 key1:'value1',key2:'value2' },headers:{ // 请求头信息 'Content-Type':'application/x-www-form-urlencoded' }.success(function(data,status,headers,config){ // 成功回调 }).error(function(data,config){ // 失败回调 }); }) }])
自定义服务服务是将一些通用性的功能逻辑进行封装方便使用,AngularJS允许将自定义服务。
App.factory('showTime',['$filter',function($filter){ // 自定义显示当前日期服务 var now = new Date(); return $filter('date')(now,'yyyy/MM/dd'); }]); // 声明依赖调用服务 App.controller('DemoController','showTime',showTime){ $scope.time = showTime; }])
App.service('showTime',showTime){ $scope.time = showTime; }]); 3. App.value('author','Name'); // 自定义常量服务 // 声明依赖调用服务 App.controller('DemoController','author',author){ $scope.author = author; }]) 在介绍服务时曾提到服务本质就是一个对象或函数,所以自定义服务就是要返回一个对象或函数以供使用。 模块加载AngularJS模块可以在被加载和执行之前对其自身进行配置。我们可以在应用的加载阶段配置不同的逻辑。 配置块通过 // 对$log服务进行配置 App.config(['$logProvider',function($logProvider){ // 关闭debug级别的信息提示 $log.debugEnabled(false); }]); App.controller('DemoController','$log',$log){ $scope.showLog = function(){ $log.log('日志'); $log.warn('警告'); // 已关闭,将不再生效 $log.debug('调试'); }; }]); // 对$filter服务进行配置,实现相同的功能 App.config(['$filterProvider',function($filterProvider){ // 注册study过滤器 $filterProvider.register('study',function(){ return function(input,arg){ return input + 'study AngularJS' + arg; } }); }]) 运行块服务也是模块形式存在的对且对外提供特定功能,除了将服务做为依赖注入进去的,然后再进行调用外,也可以直接运行相应的服务模块,AngularJS提供了 // 运行$http,$rootScope服务 App.run(['$http','$rootScope',function($http,$rootScope){ $http({ method:'post',url:'xxx.php' }).success(function(data){ $rootScpoe.data = data; }); }]) 不但如此, 路由一个应用是由若个视图组合而成的,根据不同的业务逻辑展示给用户不同的视图,路由则是实现这一功能的关键。 SPASPA(Single Page Application)指的是通单一页面展示所有功能,通过Ajax动态获取数据然后进行实时渲染,结合CSS3动画模仿原生App交互,然后再进行打包(使用工具把Web应用包一个壳,这个壳本质上是浏览器)变成一个“原生”应用。 在PC端也有广泛的应用,通常情况下使用Ajax异步请求数据,然后实现内容局部刷新,局部刷新的本质是动态生成DOM,新生成的DOM元素并没有真实存在于文档中,所以当再次刷新页面时新添加的DOM元素会“丢失”,通过单页面应可以很好的解决这个问题。 路由在后端开发中通过URL地址可以实现页面(视图)的切换,但是AngularJS是一个纯前端MVC框架,在开发单页面应用时,所有功能都在同一页面完成,所以无需切换URL地址(即不允许产生跳转),但Web应用中又经常通过链接(a标签)来更新页面(视图),当点击链接时还要阻止其向服务器发起请求,通过锚点(页内跳转)可以实现这一点。 实现单页面应用需要具备:
// 监听锚点变化然后发送请求 // hashchange事件可以监听锚点变化 window.addEventListener('hashchange',function () { // 获取锚点 var hash = location.hash; // 处理# hash = hash.slice(1); // 实例异步对象 var xhr = new XMLHttpRequest; // 将锚点做为参数传递给服务端进处理 xhr.open('get','xxx.php?hash=' + hash); xhr.send(null); xhr.onreadystatechange = function () { if(xhr.readyState == 4 && xhr.status == 200) { var result = xhr.responseText; // 将返回结果添加到页面 document.querySelector('xxx').innerHTML = result; } } }); 通过上面的例子发现在单一页面中可以能过 AngularJS对这一实现原理进行了封装,将锚点的变化封装成路由(Route),这是与后端路由的根本区别。 在1.2版前路由功能是包含在AngularJS核心代码当中,之后的版本将路由功能独立成一个模块 使用方法
<!-- Angular核心框架 --> <script type="text/javascript" src="./libs/angular.min.js"></script> <!-- Angular路由模块 --> <script type="text/javascript" src="./libs/angular-route.js"></script>
// 作为依赖传入 var App = angular.module('App',['ngRoute']);
// 通过$routeProvider配置 App.config(['$routeProvider',function($routeProvider){ // 配置路由 $routeProvider.when('/',{ template:'index' }).when('/2',{ templateUrl:'2.html' }); }])
通过 <header>头部</header> <div> <!-- 视图会被加载并渲染到此处 --> <div ng-view></div> </div> <footer>底部</footer> 路由参数
// 依赖ngRoute模块 var App = angular.module('App',['ngRoute']); // 需要对路由模块进行配置,使其正常工作 App.config(['$routeProvider',function ($routeProvider) { // : 表示变量 $routeProvider.when('/index/:id/:page/:p',{ templateUrl: 'abc.html',controller: 'IndexController' }) .otherwise({ redirectTo: '/index' }); }]); // 提供了一个专门负责获取参数的一个服务$routeParams App.controller('IndexController','$routeParams',function ($scope,$routeParams) { $scope.content = $routeParams; }]); jQlite在没有引入jQuery的前提下AngularJS实现了简版的jQuery Lite,通过 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |