Angular开发前奏

以下内容是笔者关于《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;
 };
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值