Angular JS学习笔记

之前的学习方法有点盲目,建议以后只看与工作有关的内容,并且多问那些是只和工作有关联的。

遇到问题的时候,项目不急的话,自己研究,项目急的话,马上问。

方法不对,再努力也没有用。

 

Angular JS学习网站:http://www.zouyesheng.com/angular.html#toc7   

 

 

 【  项目有关的内容 】

ng-model

ng-click

ng-options

ng-repeat

ng-if

ng-show

ng-hide

ng-controller

ng-href(有印象)

 {{}}

判断

 定义ng-model 后 对应的value值如何即时显示

 js 逻辑模块

建议:采用ajax方式请求传递数据

建议:采用对象方式传递数值,采用对象方式显示数据 ->view

 

form 表单必填项 required 的使用方法

 

其中 ,最后加上这句用来把整个页面驱动起来。

 angular.bootstrap(document.documentElement);

 

 

【 自己的理解 】

ng-model :

模板到数据的绑定,主要是通过ng-model 来完成的:

模板到数据的绑定,主要是通过 ng-model 来完成的:

  <input type="text" id="test" ng-controller="TestCtrl" ng-model="a" />
  
  <script type="text/javascript" charset="utf-8">
  var TestCtrl = function($scope){
    $scope.a = 123;
  }
这时修改 input 中的值,然后再在控制终端中使用:

  $(#test).scope().a
查看,发现变量 a 的值已经更改了。

实际上, ng-model 是把两个方向的绑定都做了。它不光显示出变量的值,也把显示上的数值变化反映给了变量。这个在实现上就简单多了,只是绑定 change 事件,然后做一些赋值操作即可。不过 ng 里,还要区分对待不同的控件。

 

ng-click :理解为事件对象本身的绑定。绑定一个click事件。

事件绑定是模板指令中很好用的一部分。我们可以把相关事件的处理函数直接写在 DOM 中,这样做的最大好处就是可以从 DOM 结构上看出业务处理的形式,你知道当你点击这个节点时哪个函数被执行了。

ng-change
ng-click
ng-dblclick
ng-mousedown
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
ng-mouseup
ng-submit
对于事件对象本身,在函数调用时可以直接使用 $event 进行传递:

  <p ng-click="click($event)">点击</p>
  <p ng-click="click($event.target)">点击</p>

 

ng-options

理解为:用来数据呈现。

 

这是一个比较牛B的控件。它里面的一个叫做 ng-options 的属性用于数据呈现。

对于给定列表时的使用。

最简单的使用方法, x for x in list :

  <form name="test_form" ng-controller="TestCtrl" ng-init="o=[0,1,2,3]; a=o[1];">
    <select ng-model="a" ng-options="x for x in o" ng-change="show()">
      <option value="">可以加这个空值</option>
    </select>
  </form>
  
  <script type="text/javascript">
  var TestCtrl = function($scope){
    $scope.show = function(){
      console.log($scope.a);
    }
  }
  
  angular.bootstrap(document.documentElement);
  </script>
在 $scope 中, select 绑定的变量,其值和普通的 value 无关,可以是一个对象:

  <form name="test_form" ng-controller="TestCtrl"
        ng-init="o=[{name: ‘AA‘}, {name: ‘BB‘}]; a=o[1];">
    <select ng-model="a" ng-options="x.name for x in o" ng-change="show()">
    </select>
  </form>
显示与值分别指定, x.v as x.name for x in o :

  <form name="test_form" ng-controller="TestCtrl"
        ng-init="o=[{name: ‘AA‘, v: ‘00‘}, {name: ‘BB‘, v: ‘11‘}]; a=o[1].v;">
    <select ng-model="a" ng-options="x.v as x.name for x in o" ng-change="show()">
    </select>
  </form>
加入分组的, x.name group by x.g for x in o :

  <form name="test_form" ng-controller="TestCtrl"
        ng-init="o=[{name: ‘AA‘, g: ‘00‘}, {name: ‘BB‘, g: ‘11‘}, {name: ‘CC‘, g: ‘00‘}]; a=o[1];">
    <select ng-model="a" ng-options="x.name group by x.g for x in o" ng-change="show()">
    </select>
  </form>
分组了还分别指定显示与值的, x.v as x.name group by x.g for x in o :

  <form name="test_form" ng-controller="TestCtrl" ng-init="o=[{name: ‘AA‘, g: ‘00‘, v: ‘=‘}, {name: ‘BB‘, g: ‘11‘, v: ‘+‘}, {name: ‘CC‘, g: ‘00‘, v: ‘!‘}]; a=o[1].v;">
    <select ng-model="a" ng-options="x.v as x.name group by x.g for x in o" ng-change="show()">
    </select>
  </form>
如果参数是对象的话,基本也是一样的,只是把遍历的对象改成 (key, value) :

  <form name="test_form" ng-controller="TestCtrl" ng-init="o={a: 0, b: 1}; a=o.a;">
    <select ng-model="a" ng-options="k for (k, v) in o" ng-change="show()">
    </select>
  </form>
  
  <form name="test_form" ng-controller="TestCtrl"
        ng-init="o={a: {name: ‘AA‘, v: ‘00‘}, b: {name: ‘BB‘, v: ‘11‘}}; a=o.a.v;">
    <select ng-model="a" ng-options="v.v as v.name for (k, v) in o" ng-change="show()">
    </select>
  </form>
  
  <form name="test_form" ng-controller="TestCtrl"
        ng-init="o={a: {name: ‘AA‘, v: ‘00‘, g: ‘==‘}, b: {name: ‘BB‘, v: ‘11‘, g: ‘==‘}}; a=o.a;">
    <select ng-model="a" ng-options="v.name group by v.g for (k, v) in o" ng-change="show()">
    </select>
  </form>
  
  <form name="test_form" ng-controller="TestCtrl"
        ng-init="o={a: {name: ‘AA‘, v: ‘00‘, g: ‘==‘}, b: {name: ‘BB‘, v: ‘11‘, g: ‘==‘}}; a=o.a.v;">
    <select ng-model="a" ng-options="v.v as v.name group by v.g for (k, v) in o" ng-change="show()">
    </select>
  </form>

 

 ng-repeat 

理解为:

7.2.1. 重复 ng-repeat
这算是唯一的一个控制标签么……,它的使用方法类型于:

  <div ng-controller="TestCtrl">
    <ul ng-repeat="member in obj_list">
      <li>{{ member }}</li>
    </ul>
  </div>
  
  
  var TestCtrl = function($scope){
    $scope.obj_list = [1,2,3,4];
  }
除此之外,它还提供了几个变量可供使用:

$index 当前索引
$first 是否为头元素
$middle 是否为非头非尾元素
$last 是否为尾元素
  <div ng-controller="TestCtrl">
    <ul ng-repeat="member in obj_list">
      <li>{{ $index }}, {{ member.name }}</li>
    </ul>
  </div>
  
  var TestCtrl = function($scope){
    $scope.obj_list = [{name: ‘A‘}, {name: ‘B‘}, {name: ‘C‘}];
  }
7.2.2. 赋值 ng-init
这个指令可以在模板中直接赋值,它作用于 angular.bootstrap 之前,并且,定义的变量与 $scope 作用域无关。

  <div ng-controller="TestCtrl" ng-init="a=[1,2,3,4];">
    <ul ng-repeat="member in a">
      <li>{{ member }}</li>
    </ul>
  </div>

 

 ng-if

 理解为:其实没有ng-if , 是模板控制语句

18.14. 示例:模板控制语句 if/else

这个示例是尝试实现:

  <div ng-controller="TestCtrl">
    <if true="a == 1">
        <p>判断为真, {{ name }}</p>
      <else>
        <p>判断为假, {{ name }}</p>
      </else>
    </if>
  
    <div>
      <p>a: <input ng-model="a" /></p>
      <p>name: <input ng-model="name" /></p>
    </div>
  </div>
考虑实现的思路:

else 与 if 是两个指令,它们是父子关系。通过 scope 可以联系起来。至于 scope 是在 link 中处理还是 controller 中处理并不重要。
true 属性的条件判断通过 $parse 服务很容易实现。
如果最终效果要去掉 if 节点,我们可以使用注释节点来“占位”。
JS 代码:

 1   var app = angular.module(‘Demo‘, [], angular.noop);
 2   
 3   app.directive(‘if‘, function($parse, $compile){
 4     var compile = function($element, $attrs){
 5       var cond = $parse($attrs.true);
 6       
 7       var link = function($scope, $ielement, $iattrs, $controller){
 8         $scope.if_node = $compile($.trim($ielement.html()))($scope, angular.noop);
 9         $ielement.empty();
10         var mark = $(‘<!-- IF/ELSE -->‘);
11         $element.before(mark);
12         $element.remove();
13   
14         $scope.$watch(function(scope){
15           if(cond(scope)){
16             mark.after($scope.if_node);
17             $scope.else_node.detach();
18           } else {
19             if($scope.else_node !== undefined){
20               mark.after($scope.else_node);
21               $scope.if_node.detach();
22             }
23           }
24         });
25       }
26       return link;
27     }
28   
29     return {compile: compile,
30             scope: true,
31             restrict: ‘E‘}
32   });
33   
34   app.directive(‘else‘, function($compile){
35     var compile = function($element, $attrs){
36       
37       var link = function($scope, $ielement, $iattrs, $controller){
38         $scope.else_node = $compile($.trim($ielement.html()))($scope, angular.noop);
39         $element.remove();
40       }
41       return link;
42     }
43   
44     return {compile: compile,
45             restrict: ‘E‘}
46   });
47   
48   app.controller(‘TestCtrl‘, function($scope){
49     $scope.a = 1;
50   });
51   
52   angular.bootstrap(document, [‘Demo‘]);
代码中注意一点,就是 if_node 在得到之时,就已经是做了变量绑定的了。错误的思路是,在 $watch 中再去不断地得到新的 if_node 。

 

ng-show  / ng-hide  同理

理解为:显示和隐藏命令

7.3.3. 显示和隐藏 ng-show ng-hide ng-switch
前两个是控制 display 的指令:

  <div ng-show="true">1</div>
  <div ng-show="false">2</div>
  <div ng-hide="true">3</div>
  <div ng-hide="false">4</div>
后一个 ng-switch 是根据一个值来决定哪个节点显示,其它节点移除:

  <div ng-init="a=2">
    <ul ng-switch on="a">
      <li ng-switch-when="1">1</li>
      <li ng-switch-when="2">2</li>
      <li ng-switch-default>other</li>
    </ul>
  </div>

 

 

{{ }}

理解为双括号,使用模板标记。

 

数据到表现的绑定,主要是使用模板标记直接完成的:

  <p>{{ w }} x {{ h }}</p>
使用 {{ }} 这个标记,就可以直接引用,并绑定一个作用域内的变量。在实现上, ng 自动创建了一个 watcher 。效果就是,不管因为什么,如果作用域的变量发生了改变,我们随时可以让相应的页面表现也随之改变。我们可以看一个更纯粹的例子:

  <p id="test" ng-controller="TestCtrl">{{ a }}</p>
  
  <script type="text/javascript">
  var TestCtrl = function($scope){
    $scope.a = 123;
  }
  angular.bootstrap(document.documentElement);
上面的例子在页面载入之后,我们可以在页面上看到 123

 

ng-controller  暂时缺少。

 

 

ng-href 理解为href 属性,一般放在a标签里面。

ng-src 控制 src 属性:

  <img ng-src="{{ ‘h‘ + ‘ead.png‘ }}" />
ng-href 控制 href 属性:

  <a ng-href="{{ ‘#‘ + ‘123‘ }}">here</a>
总的来说:

ng-src src属性
ng-href href属性
ng-checked 选中状态
ng-selected 被选择状态
ng-disabled 禁用状态
ng-multiple 多选状态
ng-readonly 只读状态
注意: 上面的这些只是单向绑定,即只是从数据到展示,不能反作用于数据。要双向绑定,还是要使用 ng-model 。

 

 Ajax 请求

11. AJAX

ng 提供了基本的 AJAX 封装,你直接面对 promise 对象,使用起来还是很方便的。

11.1. HTTP请求

基本的操作由 $http 服务提供。它的使用很简单,提供一些描述请求的参数,请求就出去了,然后返回一个扩充了 success 方法和 error 方法的 promise 对象(下节介绍),你可以在这个对象中添加需要的回调函数。

  var TestCtrl = function($scope, $http){
    var p = $http({
      method: ‘GET‘,
      url: ‘/json‘
    });
    p.success(function(response, status, headers, config){
        $scope.name = response.name;
    });
  }
$http 接受的配置项有:

method 方法
url 路径
params GET请求的参数
data post请求的参数
headers 头
transformRequest 请求预处理函数
transformResponse 响应预处理函数
cache 缓存
timeout 超时毫秒,超时的请求会被取消
withCredentials 跨域安全策略的一个东西
其中的 transformRequest 和 transformResponse 及 headers 已经有定义的,如果自定义则会覆盖默认定义:

 1   var $config = this.defaults = {
 2     // transform incoming response data
 3     transformResponse: [function(data) {
 4       if (isString(data)) {
 5         // strip json vulnerability protection prefix
 6         data = data.replace(PROTECTION_PREFIX, ‘‘);
 7         if (JSON_START.test(data) && JSON_END.test(data))
 8           data = fromJson(data, true);
 9       }
10       return data;
11     }],
12   
13     // transform outgoing request data
14     transformRequest: [function(d) {
15       return isObject(d) && !isFile(d) ? toJson(d) : d;
16     }],
17   
18     // default headers
19     headers: {
20       common: {
21         ‘Accept‘: ‘application/json, text/plain, */*‘,
22         ‘X-Requested-With‘: ‘XMLHttpRequest‘
23       },
24       post: {‘Content-Type‘: ‘application/json;charset=utf-8‘},
25       put:  {‘Content-Type‘: ‘application/json;charset=utf-8‘}
26     }
27   };
注意它默认的 POST 方法出去的 Content-Type

对于几个标准的 HTTP 方法,有对应的 shortcut :

$http.delete(url, config)
$http.get(url, config)
$http.head(url, config)
$http.jsonp(url, config)
$http.post(url, data, config)
$http.put(url, data, config)
注意其中的 JSONP 方法,在实现上会在页面中添加一个 script 标签,然后放出一个 GET 请求。你自己定义的,匿名回调函数,会被 ng 自已给一个全局变量。在定义请求,作为 GET 参数,你可以使用 JSON_CALLBACK 这个字符串来暂时代替回调函数名,之后 ng 会为你替换成真正的函数名:

  var p = $http({
    method: ‘JSONP‘,
    url: ‘/json‘,
    params: {callback: ‘JSON_CALLBACK‘}
  });
  p.success(function(response, status, headers, config){
      console.log(response);
      $scope.name = response.name;
  });
$http 有两个属性:

defaults 请求的全局配置
pendingRequests 当前的请求队列状态
  $http.defaults.transformRequest = function(data){console.log(‘here‘); return data;}
  console.log($http.pendingRequests);

 

 

form表单中的required

 

.5.1. form
form 是核心的一个控件。 ng 对 form 这个标签作了包装。事实上, ng 自己的指令是叫 ng-form 的,区别在于, form 标签不能嵌套,而使用 ng-form 指令就可以做嵌套的表单了。

form 的行为中依赖它里面的各个输入控制的状态的,在这里,我们主要关心的是 form 自己的一些方法和属性。从 ng 的角度来说, form 标签,是一个模板指令,也创建了一个 FormController 的实例。这个实例就提供了相应的属性和方法。同时,它里面的控件也是一个 NgModelController 实例。

很重要的一点, form 的相关方法要生效,必须为 form 标签指定 name 和 ng-controller ,并且每个控件都要绑定一个变量。 form 和控件的名字,即是 $scope 中的相关实例的引用变量名。

  <form name="test_form" ng-controller="TestCtrl">
    <input type="text" name="a" required ng-model="a"  />
    <span ng-click="see()">{{ test_form.$valid }}</span>
  </form>
  
  var TestCtrl = function($scope){
  
    $scope.see = function(){
      console.log($scope.test_form);
      console.log($scope.test_form.a);
    }
  
  }
除去对象的方法与属性, form 这个标签本身有一些动态类可以使用:

ng-valid 当表单验证通过时的设置
ng-invalid 当表单验证失败时的设置
ng-pristine 表单的未被动之前拥有
ng-dirty 表单被动过之后拥有
form 对象的属性有:

$pristine 表单是否未被动过
$dirty 表单是否被动过
$valid 表单是否验证通过
$invalid 表单是否验证失败
$error 表单的验证错误
其中的 $error 对象包含有所有字段的验证信息,及对相关字段的 NgModelController 实例的引用。它的结构是一个对象, key 是失败信息, required , minlength 之类的, value 是对应的字段实例列表。

注意,这里的失败信息是按序列取的一个。比如,如果一个字段既要求 required ,也要求 minlength ,那么当它为空时, $error 中只有 required 的失败信息。只输入一个字符之后, required 条件满足了,才可能有 minlength 这个失败信息。

  <form name="test_form" ng-controller="TestCtrl">
    <input type="text" name="a" required ng-model="a"  />
    <input type="text" name="b" required ng-model="b" ng-minlength="2" />
    <span ng-click="see()">{{ test_form.$error }}</span>
  </form>
  
  var TestCtrl = function($scope){
    $scope.see = function(){
      console.log($scope.test_form.$error);
    }
  }

 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。