首页
IT
登录
6mi
u
盘
搜
搜 索
IT
Angular开发前奏
Angular开发前奏
xiaoxiao
2021-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
)