问题1:ng-app指令的使用以及自定义指令
<!doctype html> <!--这里的ng-app的属性值就是模块的名称,也就是 angular.module("MyModule",[])中的MyModule--> <html ng-app="MyModule"> <head> <Meta charset="utf-8"> </head> <body> <hello></hello> <!--这个标签被完全替换为'<div>Hi everyone!</div>',这一点很重要的--> </body> <script src="js/angular-1.3.0.js"></script> <!--引入指令--> <script src="HelloAngular_Directive.js"></script> </html>我们看看指令本身的代码是如何定义的
var myModule = angular.module("MyModule",[]); //创建一个模块 myModule.directive("hello",function() { //这里的指令为hello指令,而且是Element类型,返回的template就是用于替换hello的部分,而replace指定了用template值替换了hello这个标签的内容 return { restrict: 'E',template: '<div>Hi everyone!</div>',replace: true } });问题2:我们来理解一下angularjs的MVC模式
<!doctype html> <!--这里的ng-app指令表明下面的所有的指令全部让angularjs处理,只有被具有ng-app属性的DOM元素包含的元素才会受到angularjs的影响--> <html ng-app> <head> <Meta charset="utf-8"> </head> <body> <!--这里指定了一个controller,这个controller是view视图和数据之间的桥梁--> <div ng-controller="HelloAngular"> <!--这里指定的视图,也就是用于显示的view--> <p>{{greeting.text}},Angular</p> </div> </body> <script src="js/angular-1.3.0.js"></script> <script src="HelloAngular_MVC.js"></script> </html>下面是控制器的代码
function HelloAngular($scope) { $scope.greeting = { text: 'Hello' }; }问题3:通用controller是通过$scope来完成继承的,但是我们不建议使用通用controller,而是使用服务
<!doctype html> <html ng-app> <head> <Meta charset="utf-8"> </head> <body> <!--这里是CommonController的部分,这个controller指定了内部两个controller共有的逻辑--> <div ng-controller="CommonController"> <!--这里是内部第一个controller--> <div ng-controller="Controller1"> <p>{{greeting.text}},Angular</p> <button ng-click="test1()">test1</button> </div> <!--这里是内部第二个controller--> <div ng-controller="Controller2"> <p>{{greeting.text}},Angular</p> <button ng-click="test2()">test2</button> <button ng-click="commonFn()">通用</button> </div> </div> </body> <script src="js/angular-1.3.0.js"></script> <script src="MVC3.js"></script> </html>下面是三个controller的代码
//这个通用的controller指定的是两个controller都具有的方法 function CommonController($scope){ $scope.commonFn=function(){ alert("这里是通用功能!"); }; } //这里是第一个controller指定了其特有的功能 function Controller1($scope) { $scope.greeting = { text: 'Hello1' }; $scope.test1=function(){ alert("test1"); }; } //这里是第一个controller指定了其特有的功能 function Controller2($scope) { $scope.greeting = { text: 'Hello2' }; $scope.test2=function(){ alert("test2"); } }
注意:其实$scope是一个POJO(plain Old JavaScript Object);$scope提供了一些工具方法,如$watch,$apply等;$scope是表达式执行环境,也就是作用域;$scope是树形结构和DOM标签平行;子$scope继承父$scope的所有的属性和方法;每一个angular应用只有一个根$scope,一般位于ng-app上;$scope可以用于传播事件,类似DOM可以往上也可以往下;可以用angular.element($0).scope进行调试。总之,$scope不仅仅是MVC的基础,而且也是双向数据绑定的基础!
问题4:ng-repeat的使用,同时指定了$scope会继承$rootScope,就像原型链一样
<!doctype html> <html ng-app> <head> <Meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="Scope1.css" /> </head> <body> <div class="show-scope-demo"> <!--这里是第一个controller,是GreetCtrl--> <div ng-controller="GreetCtrl"> Hello {{name}}! </div> <!--这里是第二个controller,是ListCtrl--> <div ng-controller="ListCtrl"> <ol> <!--ng-repeat指令的使用--> <li ng-repeat="name in names"> {{name}} from {{department}} </li> </ol> </div> </div> </body> <script src="js/angular-1.3.0.js"></script> <script src="Scope1.js"></script> </html>下面是两个controller,同时注意这时候$scope会继承$rootScope的属性
//第一个controller指定了$scope和$rootScope,并且在他们上面都绑定了属性值 function GreetCtrl($scope,$rootScope) { $scope.name = 'World'; $rootScope.department = 'Angular'; } //这里也绑定了$scope属性值 function ListCtrl($scope) { $scope.names = ['Igor','Misko','Vojta']; }问题5:我们来看看$emit和$broadcast用于事件触发的不同
<!doctype html> <html ng-app> <head> <Meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="Scope1.css" /> </head> <body> <!--第一个控制器EventController--> <div ng-controller="EventController"> Root scope <tt>MyEvent</tt> count: {{count}} <ul> <!--这里是内部的controller,也是通过EventController来控制的--> <li ng-repeat="i in [1]" ng-controller="EventController"> <!--这里是调用$emit--> <button ng-click="$emit('MyEvent')"> $emit('MyEvent') </button> <!--这里是调用$broadcast--> <button ng-click="$broadcast('MyEvent')"> $broadcast('MyEvent') </button> <br> Middle scope <tt>MyEvent</tt> count: {{count}} <!--EventController--> <ul> <li ng-repeat="item in [1,2]" ng-controller="EventController"> Leaf scope <tt>MyEvent</tt> count: {{count}} </li> </ul> </li> </ul> </div> </body> <script src="js/angular-1.3.0.js"></script> <script src="Scope2.js"></script> </html>下面是控制器的代码
function EventController($scope) { $scope.count = 0; //这个$scope具有$on方法来监测具体的事件,这里是监测'MyEvent'事件,每次监听到这个事件就把count++ $scope.$on('MyEvent',function() { $scope.count++; }); }通过测试我们发现$emit触发事件会导致从同级作用域不断往上传播,但是$broadCast会使得事件从同级作用域不断往下传播。但是不管是$emit还是$broadcast都会在同级作用域之间传播。
问题6:我们看看如何让angularjs实现了站内路由,其本质还是通过hash来完成的
<!doctype html> <html ng-app="bookStoreApp"> <head> <Meta charset="UTF-8"> <title>BookStore</title> <!--当express直接访问/的时候被重定向到这里,然后静态资源文件如js等都是在public目录下进行加载的--> <script src="1.3.0.14/angular.js"></script> <script src="1.3.0.14/angular-route.js"></script> <script src="1.3.0.14/angular-animate.js"></script> <!--然后加载app.js,这是一个模块,定义了该模块依赖的一些如控制器,过滤器,服务,指令等--> <script src="app.js"></script> <script src="controllers.js"></script> <script src="filters.js"></script> <script src="services.js"></script> <script src="directives.js"></script> </head> <body> <!--这里是视图显示区域--> <div ng-view> </div> </body> </html>
我们再来看看app.js中如何指定了依赖模块,同时是如何实现站内路由的。注意:ng-view是由ngRouter模块提供的一个特殊指令,他的独特之处是在HTML中给$router对应的视图内容占位,他会创建自己的作用域并将模版嵌套在内部。ng-view是一个优先级为1000的终极指令,angularjs不会运行同一个元素上的低优先级指令。ngView指令遵循下面的规则:
。每次触发$routeChangeSuccess事件视图都会更新
。如果某个模版和当前的路由相关联:
(1)创建一个新的作用域;(2)移除上一个视图,同时上一个作用域也会被清除;(3)将新的作用域和当前模版关联在一起;(4)如果路由中有相关的定义,那么就把对应的控制器和当前作用域关联起来;(5)触发$viewContentLoaded事件;(6)如果提供了onload属性,调用该属性指定的函数。
//定义了一个模块bookStoreApp,第二个参数是该模块依赖的模块。其中<bookStoreCtrls>是一个模块,其中封装了两个控制器分别为bookStoreCtrls,BookListCtrl //其中模块<bookStoreFilters>是一个过滤器 //模块<bookStoreServices>定义了一个服务 //模块<bookStoreDirectives>定义了一个指令集合 var bookStoreApp = angular.module('bookStoreApp',[ 'ngRoute','ngAnimate','bookStoreCtrls','bookStoreFilters','bookStoreServices','bookStoreDirectives' ]); //在这个app模块中我们配置了路由,如果是访问了hello就会重定向到http://localhost:3008/hello这个视图文件 //同时这个视图文件通过HelloCtrl这个控制器进行渲染 bookStoreApp.config(function($routeProvider) { $routeProvider.when('/hello',{ templateUrl: 'http://localhost:3008/hello',controller: 'HelloCtrl' }).when('/list',{ //如果是list那么渲染视图http://localhost:3008/bookList,同时渲染工作由BookListCtrl来完成 templateUrl:'http://localhost:3008/bookList',controller:'BookListCtrl' }).otherwise({ redirectTo: '/hello' }) });很显然是通过模块的config方法来完成的,同时实现了注入$routeProvider对象,最后通过这个对象的when...otherwise方法来实现路由的。记住,上面的ng-view是指定了视图的显示区域。其站内路由还是通过hash来完成的:
我们谈谈ajax:ajax的页面浏览器回退按钮会失效;无法分享页面,也就无法加书签;SEO无法起作用,于是就有了前端路由的观点。前端路由的原理:通过hash值#;HTML5提供的API也可以完成;路由的核心是给应用定义"状态";使用路由会影响应用整体的编码方式(预先定义好状态);考虑兼容性问题与优雅降级。
问题7:我们建议在定义controller时候不是在函数中直接定义,而是在模块中定义:
第一种方式直接在函数中定义:
function HelloAngular($scope) { $scope.greeting = { text: 'Hello' }; }第二种方式是首先定义模块,然后在模块中定义控制器,这是我们推荐的方式:
var helloModule=angular.module('HelloAngular',[]); helloModule.controller('helloNgCtrl',['$scope',function($scope){ $scope.greeting = { text: 'Hello' }; }]);
我们推荐下面的编码逻辑:
问题7:使用ng-bind防止页面快速刷新或者网速较慢的时候看到源代码{{greeting.text}}
<!doctype html> <html ng-app> <head> <Meta charset="utf-8"> </head> <body> <!--引用一个控制器HelloAngular--> <div ng-controller="HelloAngular"> <!--ng-bind用于绑定,之所有使用ng-bind而不是使用{{greeting.text}}是因为在网速慢的时候或者快速刷新的时候会看到{{greeting.text}}这个源代码--> <p><span ng-bind="greeting.text"></span>,Angular</p> </div> </body> <script src="js/angular-1.3.0.js"></script> <script src="HelloAngular_MVC.js"></script> </html>控制器代码如下(建议用模块来定义):
function HelloAngular($scope) { $scope.greeting = { text: 'Hello' }; }问题8:使用ng-class来添加class,而不是使用为$scope添加属性这种方式
<!doctype html> <html ng-app="MyCSSModule"> <head> <Meta charset="utf-8"> <link rel="stylesheet" href="NgClass.css"> </head> <body> <!--这里是控制器HeaderController,如果isError为true那么添加error类,如果isWarning为true那么谈价类warning就可以了--> <div ng-controller='HeaderController'> <!--这里是视图,其类名和提示信息都是动态添加的,这一点要弄清楚--> <div ng-class='{error: isError,warning: isWarning}'>{{messageText}}</div> <button ng-click='showError()'>Simulate Error</button> <button ng-click='showWarning()'>Simulate Warning</button> </div> </body> <script src="js/angular-1.3.0.js"></script> <script src="NgClass.js"></script> </html>同时相应的点击事件来修改数据模型中的值,进而使得视图内容能够动态改变,而视图的样式通过ng-class来修改了。除了ng-class另外一种使用 细说Angular ng-class
var myCSSModule = angular.module('MyCSSModule',[]); //定义一个模块MyCSSModule myCSSModule.controller('HeaderController',//为模块定义个控制器HeaderController function($scope) { $scope.isError = false; $scope.isWarning = false; $scope.showError = function() { $scope.messageText = 'This is an error!'; $scope.isError = true; $scope.isWarning = false; }; $scope.showWarning = function() { $scope.messageText = 'Just a warning. Please carry on.'; $scope.isWarning = true; $scope.isError = false; }; } ])问题8:使用ng-show来控制元素的隐藏和显示
<!doctype html> <html ng-app="MyCSSModule"> <head> <Meta charset="utf-8"> </head> <body> <div ng-controller='DeathrayMenuController'> <!--点击的时候就触发toggleMenu逻辑,在该方法里面修改了数据模型的值--> <button ng-click='toggleMenu()'>Toggle Menu</button> <!--ng-show指令通过判断表达式的值进而决定是否应该显示内容--> <ul ng-show='menuState.show'> <li ng-click='stun()'>Stun</li> <li ng-click='disintegrate()'>Disintegrate</li> <li ng-click='erase()'>Erase from history</li> </ul> <div/> </body> <script src="js/angular-1.3.0.js"></script> <script src="NgShow.js"></script> </html>控制器内部通过非表达式来实现开关效果
var myCSSModule = angular.module('MyCSSModule',[]); //这里定义一个模块<MyCSSModule>,在模块上定义一个控制器DeathrayMenuController myCSSModule.controller('DeathrayMenuController',function($scope) { $scope.menuState={show:false}; $scope.toggleMenu = function() { //这里的toggleMenu通过非符号'!'就能够动态改变了 $scope.menuState.show = !$scope.menuState.show; }; } ])上面演示了如何实现jQuery中的toggleClass效果 原文链接:https://www.f2er.com/angularjs/149591.html