Angular开发前奏

    xiaoxiao2021-03-25  93

    以下内容是笔者关于《Angular开发中文版》一书的读书笔记,如若想获取更多相关深入知识以及应用,请阅读Angular开发中文版原文。 1.尽管原始风格模型在简单场景中可以运行,对于绝大多数应用,需要创建一个模型对象包含数据. 创建一个message模型对象,用来存储someText,因此而不是: var someText='You have started your journey'; 应该是这样: var message={}; message.someText='You have started your journey'; 2.ng-bind和{{}}两个数据绑定方式的选择 {{}}双括号插补语法,阅读起来更加自然,需要更少的输入,然而,这和ng-bind产生等价的输出. 在应用的index.html每次加载页面,在Angular用数据替换大括号之前,用户是有可能看到未渲染的模板. 结论:我们可以选择在大多数模板中使用{{}},然而,为了在index.html页面做数据绑定,用ng-bind代替之. 3.ng-submit指令 在form表单中可以接受一个ng-submit指令,比如:ng-submit='doSometing()' ng-submit指令会自动的阻止浏览器发送默认的POST/GET动作. 4.内联样式和设值结合起来,例如:style='{{设值}}' 虽然是一种小聪明,但是这种技术在组合样式名时有着间接层次的缺点,虽然能很容易的理解,但是很快变得难以管理,Angular提供了ng-class和ng-style标识符,每一个都需要一个表达式,表达式执行结果可能是下列之一: 一个字符串,表示空间间隔开的样式名,通过数据的双向绑定(不推荐) 1) .classname{   } <div ng-class='{{classname}}' />   //可以使用空格分割,添加多个class样式 一个样式名数组 .show{   } .hide{   } <div ng-class="{true:'show',false:'hide'}[className]"></div> 当className为true时,class样式为show,为false时,class样式为hide. 一个样式名到布尔值的映射,通过key/value的方式 1) .error{  backgroud-color:red; } .warning{  backgroud-color:yellow; } <div ng-class='{error:isError,warning:isWarning}' ></div> 当isError,isWarning值为true时,样式将生效. 2) .selected{  backgroud-color:lightgreen; } <tr ng-repeat='row in rows'     ng-click='selected($index)'     ng-class='{selected:$index==selectedRow}' > </tr> $scope.selected=function(index){  $scope.selectedRow=index; } 5.src和href属性的建议 当数据绑定到一个<img>或者<a>标签时,在src和href中使用{{}}的路径不能正常运行,因为对于其他内容,浏览器是并行加载图片的,Angular没有机会拦截数据绑定的请求. 比如虽然<img>直接的写法可能是这样的: <img src='/myapp/{{mypic}}' /> 然而这样的写法不会正常运行,我们需要改成以下写法: <img ng-src='/myapp/{{mypic}}' /> 与此类似,<a>标签应该使用hg-href: <a ng-href='/myapp/{{myUrl}}' /> 6.用$scope.$watch观察模型变化 $watch(watchFn,watchAction,deepWatch); watchFn:这个参数是一个Angular表达式字符串或者是一个返回监控的模型的当前值的函数 watchAction:这是一个回调函数,function(newValue,oldValue,scope){} deepWatch:如果希望监视数组中的私有元素或者对象中的属性,而不仅是一个简单的值时,应该将此值设置为true 返回值:一个取消监听的函数. 例如:监视一个属性之后取消继续监听,使用以下代码: var dereg=$scope.$watch('someModel.someProperty',callbackChange()); dereg();//取消监听 监视多个事物 假如希望监视多个属性或者对象,当他们发生改变时执行一个函数,有两种方式: 1)把他们放到一个对象或者数组中,同时传递deepWatch为true. 2)监视这些属性的链接串   第一种场景:   $scope.$watch('Object.a + Object.b',callMethod());   甚至可以写一个函数,返回连接串.   第二种场景:   $scope.$watch('Object',callMethod(),true);   只要Object对象中的任意一个属性发生变化,就会掉一批调用callMethod(),在数组上运行很好,同样适合对象. 7.Chrome调试扩展应用:Batarang 8.服务,依赖注入 var shoppingModule=angular.module('ShoppingModule',[]); //定义一个获取公共数据的服务 shoppingModule.factory('@items',function(){  var items={};  items.query=function(){   return [    {name:'YZR'},    {name:'YZJ'},    {name:'LYF'}   ];  };  return items; }); shoppingModule.controller('ShoppingController',function($scope,@items){  $scope.items=@items.query; }); <html ng-app='ShoppingModule'> <body ng-controller="ShoppingController">   <table>     <tr ng-repeat="item in items">      <td>{{item.name}}</td>     </tr>   </table> </body> </html> 创建服务的方法: provider(name,Object OR constructor()); 一个可配置的,有复杂逻辑的服务,如果你传递了一个对象,那么它应该有一个叫$get的函数返回这个服务的实例.否则的话,Angular假设你已经产生了一个构造函数,当被调用时,创建这个实例. factory(name,$getFunction()) 一个不可配置的,有复杂逻辑的服务,你指定一个函数,当被调用时,返回服务实例 service(name,constructor) 一个不可配置的,简单逻辑的服务,Angular调用它来创建服务实例. 9.模块与模块之间的依赖 var  appModule=angular.module('app',['app02','app02']); 10.用过滤器格式化数据 Angular自带了几个过滤器:currency,date,number,uppercase,lowercase等 currency是转化为美元单位 {{12.9 | currency}}  =>  $12.9 number是删除小数点后的数字,需要带一个要舍入小数点位数的参数 {{12.9 | currency | number:0}} 创建自定义过滤器: var homeModule=angular.modlue('HomeModule',[]); homeModule.filter('titleCase',function(){  var titleCaseFilter=function(input){   var words=input.split(' ');   for(var i=0;i<words.length;i++){    words[i]=words[i].charAt(0).toUpperCase()+ words[i].slice(1);   }   return words.join(' ');  };  return titleCaseFilter; }); <html ng-app='HomeModule'> <body ng-controller="HomeController">  <h1>{{pageHeading | titleCase}}</h1> </body> </html> homeModule.controller('HomeController',function($scope){  $scope.pageHeading=" this is test text"; }); 11.路由Route的使用($routeProvider,$routeParams) 可以根据配置从路由中选择跳转的URL. 一般由主视图和子视图组成,子视图的显示由配置的路由进行匹配. 主视图:index.html: <html ng-app='app'>  <head></head>  <body>   <div ng-view></div>  </body> </html> ng-view:告诉Angular子视图应展示的地方 子视图:列表展示 list.html <table>  <th>   <td>学号</td>   <td>姓名</td>  </th>  <tr ng-repeat=' student in students'>      <td><a ng-href='#/view/{{student.id}}'>{{student.no}}</a></td>   <td>{{student.name}}</td>  </tr> </table> 子视图:详细信息 detail.html <div>学号:{{student.no}}</div> <div>姓名{{student.name}}</div> <div>  <span ng=repeat='hobby in student.hobbies'>{{hobby}}</span> </div> <a ng-href='#/'>返回</a> 脚本: var appModule=angular.module('app',[]); //配置路由 appModule.config(function($routeProvider){  $routeProvider.when('/',{   controller:listController,   templateUrl:'list.html'  }).when('/view/:id',{   controller:detailController,   templateUrl:'detail.html'  }).otherwise({   redirectTo:'/'  }); }); //模拟数据源 var students={}; student=[{  id:1,no:'2011344223',name:'YZR',hobbies:['eat','sleep'] },{  id:2,no:'2011XXXXXX',name:'LYF',hobbies:['read','TV'] }]; //实现控制器 appModule.controller('listController',function($scope){  $scope.students=students; }); appModule.controller('detailController',function($scope,$routeParams){  $scope.student=students[$routeParams.id-1]; }); 12.用指令实现自定义Dom元素:directive <html ng=app='app'>  <head></head>  <body>   <hello></hello>  </body> </html> var appModule=angular.module('app',[]); appModule.directive('hello',function(){  return {   restrict:E,   template:'<div>hello world</div>',   replace:true  }; }); 1) restrict有四种方式: E:元素  A:属性  C:样式类  M:注释 2) priority (数字),可选参数,指明指令的优先级,若在单个DOM上有多个指令,则优先级高的先执行; 3) terminal (布尔型),可选参数,可以被设置为true或false,若设置为true,则优先级低于此指令的其他指令则无效,不会被调用(优先级相同的还是会执行) 4) template(字符串或者函数)可选参数,可以是: (1)一段HTML文本 (2)一个函数,可接受两个参数tElement和tAttrs     其中tElement是指使用此指令的元素,而tAttrs则实例的属性,它是一个由元素上所有的属性组成的集合(对象) 比如:<hello name = '我是tAttrs.name'></hello> 5) templateUrl(字符串或者函数),可选参数,可以是 (1)一个代表HTML文件路径的字符串  文件是存放在服务器上的,当服务器运行起来之后,由于加载html模板是异步的,若加载大量的时候回拖慢网站的速度,可以使用下面两种方式:  缓存模板:在本地上缓存模板  <script type='text/ng-template' id='view.html'>        <div>this is content</div>     </script>     此时templateUrl:'view.html'即可     另外一种缓存写法:     appModule.run(['$templateCache',function($templateCache){      $templateCache.put('view.html',"<div>this a content</div>");     }]); (2)一个函数,可接受两个参数tElement和tAttrs(大致同上) 6) replace (布尔值),默认值为false,设置为true时候,Dom标签(<hello>)会被替换掉,否则还会显示在Dom中. 7) scope (1)默认值false。表示继承父作用域; (2)true。表示继承父作用域,并创建自己的作用域(子作用域); (3){}。表示创建一个全新的隔离作用域;  @ 局部 scope 属性     @ 方式局部属性用来访问 directive 外部环境定义的字符串值,主要是通过 directive 所在的标签属性绑定外部字符串值。这种绑定是单向的,即父 scope 的绑定变化,directive 中的 scope 的属性会同步变化,而隔离 scope 中的绑定变化,父 scope 是不知道的。     <div isolated-directive name="{{name}}"></div>     scope: {    name: "@"   }   template: 'Say:{{name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">'     = 局部 scope 属性     = 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。     意思是,当你想要一个双向绑定的属性的时候,你可以使用=来引入外部属性。无论是改变父 scope 还是隔离 scope 里的属性,父 scope 和隔离 scope 都会同时更新属性值,因为它们是双向绑定的关系。     <div isolated-directive user="userBase"></div>     scope: {    user: "="   }   template: 'Say:{{user.name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="user.name"/>'   & 局部 scope 属性  & 方式提供一种途经是 directive 能在父 scope 的上下文中执行一个表达式。此表达式可以是一个  <div isolated-directive action="click()"></div>  function。  scope: {    action: "&"   }   template: '<input type="button" value="在directive中执行父scope定义的方法" ng-click="action()"/>' 8) transclude  如果不想让指令内部的内容被模板替换,可以设置这个值为true。一般情况下需要和ngTransclude指令一起使用。 比如:template:"<div>hello every <div ng-transclude></div></div>",这时,指令内部的内容会嵌入到ng-transclude这个div中。也就是变成了<div>hello every <div>这是指令内部的内容</div></div>。默认值为false;这个配置选项可以让我们提取包含在指令那个元素里面的内容,再将它放置在指令模板的特定位置。 9) controller   可以是一个字符串或者函数。指定一个控制器.   (1)controller:'appController'   (2)controller:function($scope, $element, $attrs, $transclude,$log) {     //$transclude()就是嵌入的内容      $transclude(function (clone) {       var a = angular.element('<p>'); //创建一个<p>       a.css('color', $attrs.mycolor); //设置属性       a.text(clone.text()); //设置文本       $element.append(a); //将元素添加到Dom中     });     $log.info("hello everyone");   } 注意:使用$transclude会生成一个新的作用域。 默认情况下,如果我们简单使用$transclude(),那么默认的其作用域就是$transclude生成的作用域 但是如果我们实用$transclude($scope,function(clone){}),那么作用域就是directive的作用域了 那么问题又来了。如果我们想使用父作用域呢 可以使用$scope.$parent 同理想要一个新的作用域也可以使用$scope.$parent.new(); controller,transclude,restrict一起使用. 10) controllerAs  控制器别名  controller:'someController',  controllerAs:'mainController' 11) require 字符串代表另一个指令的名字,它将会作为link函数的第四个参数。 var app = angular.module('myApp', []);  app.directive('outerDirective', function() {   return {   scope: {},   restrict: 'AE',   controller: function($scope) {    this.say = function(someDirective) {    console.log('Got:' + someDirective.message);    };   }   };  });  app.directive('innerDirective', function() {   return {   scope: {},   restrict: 'AE',   require: '^outerDirective',   link: function(scope, elem, attrs, controllerInstance) {    scope.message = "Hi,leifeng";    controllerInstance.say(scope);   }   };  });  app.directive('innerDirective2', function() {   return {   scope: {},   restrict: 'AE',   require: '^outerDirective',   link: function(scope, elem, attrs, controllerInstance) {    scope.message = "Hi,shushu";    controllerInstance.say(scope);   }   };  });  上面例子中的指令innerDirective和指令innerDirective2复用了定义在指令outerDirective的controller中的方法 也进一步说明了,指令中的controller是用来让不同指令间通信用的。 另外我们可以在require的参数值加上下面的某个前缀,这会改变查找控制器的行为: (1)没有前缀,指令会在自身提供的控制器中进行查找,如果找不到任何控制器,则会抛出一个error (2)?如果在当前的指令没有找到所需的控制器,则会将null传给link连接函数的第四个参数 (3)^如果在当前的指令没有找到所需的控制器,则会查找父元素的控制器 (4)?^组合 12) link和controller   在使用的时候,一般场景下都不想要使用controller,只需要把逻辑写在link中就可以了;用controller的场景就是该指令(假设为a)会被其他指令(假设为b)require的时候,这样就会在b指令的link函数中传入这个controller(如果require多个的话,传入的是一个数组,数组中存放的是每一个require的指令对应的controller),目的很显然是为了指令间进行交流的。   link函数签名:   function(scope,element,attrs,controller){} 13)表单合法性验证 $valid <form name="addUser" ng-controller="AddUserController"> <div ng-model="message"></div> <div>姓名:<input type="text" name="UserName" ng-model="user.name" require/></div> <div>电子邮件:<input type="email" name="UserEmail" ng-model="user.email" require></div> <div>薪水:<input type="number" name="UserSalary" ng-model="user.salary" ></div> <button ng-click="addUser()" ng-disabled="!addUser.$valid"></button> </form> function AddUserController($scope){  $scope.message="";  $scope.addUser=function(){   $scope.message="提交成功,姓名:"+$scope.user.name+".邮箱:"+$scope.user.email;  }; }
    转载请注明原文地址: https://ju.6miu.com/read-16559.html

    最新回复(0)