angularjs 知识点

1. $eval 方法对绑定的属性值直接进行解析

<input type='text' ng-model = 'expr2/>
<span ng-bing='$eval(expr2)'></span>



$scope.expr2 = '20 + 1 | number:0';

2. ng-repeat

指令复制元素-在复制过程中可以添加元素相应的属性-专有变量

$first

$last

$middle

$index

<span>{{$first?'yes':'no"}}</span

3. 添加元素样式

$scope.red = "red";
<div ng-class="{{red}}"></div>
<div class="{{red}}"></div>

字符串数组形式添加样式

$scope.blnfocus = false;
<div ng-class="{true:'red',false:'green'}[blnfocus]"></div>

定义key/value对象的方式添加多个css样式

$scope.a = false;
$scope.b = true;
<div ng-class="{'red':a,'green':b}"></div>

4. 控制元素显示,隐藏状态

页面中调用ng-show,ng-hide,ng-switch指令绑定$scope对象的属性值

ng-switch 指令中 on可有可无,当on于多个或某个ng-switch-when指令的元素匹配时,这些元素显示,如果没有匹配的ng-switch-default显示.

<div ng-show = {{isShow}}> div </div>
<div ng-hide = {{isHide}}>hide</div>
<ul ng-switch on={{switch}}>
    <li ng-switch-when="1">taoguorong</li>
    <li ng-switch -default>more</li>
</ul>

5. 表单基本验证功能

$pristine:表单或控件内容是否未输入过

$dirty:表单或控件内容是否已输入过

$valid:表单或控件内容是否已验证通过

$invalid:表单或空间内容是否未验证通过

$error:表单或控件验证时的错误提示信息

<form name="temp_form" ng-submit="save()">
    <div>
        <input name="t_email" ng-model = "email" type="email" required/>
        <span ng-show="temp_form.t_email.$error.required>
            邮件不能为空
       </span>
       <span ng-show="temp_form.t_email.$error.email>
           邮件格式不对
       </span
    </div>
     <input type = "button" ng-disabled="temp_form.$invalid" value="提交"/>
</form>    

6. 表单中的checkbox控件和redio控件

通过ng-model绑定控制器的属性,一旦绑定完成,首次加载时,将以绑定的值作为控件的初始化状态.

<form name="temp_form" ng-submit="save()">
    <div>
        <input name="t_email" ng-model = "email" type="email" required/>
        <span ng-show="temp_form.t_email.$error.required>
            邮件不能为空
       </span>
       <span ng-show="temp_form.t_email.$error.email>
           邮件格式不对
       </span
    </div>
    <div>
        <input type="checkbox" ng-model = "a"  ng-true-value="同意" ng-false-value = "不同意">同意
    </div>
     <div>
        <input type="rediio" ng-model = "a"  value=""><input type="rediio" ng-model = "a"  value=""></div>
     <input type = "button" ng-disabled="temp_form.$invalid" value="提交"/>
</form>        

ng-true-value表示选中后返回的值,后者表示没有被选中时返回的值,redio只有被选中的会返回其被选中的值.

7. 表单中的select控件

可以借助ng-option指令属性,将数组,对象类型的数据添加到<option>元素中,同时还能在添加数据时进行分组显示.

绑定简单的数据类型:

通过ng-option指令属性值,采用...for...in...格式将数组与<select>控件绑定

绑定简单的对象数据

通过ng-option指令属性值,采用...as...for...in...格式将对象与<select>控件绑定,as前面部分对应元素的value值,用于选中时获取,as后面部分对应元素的text值,用于直接显示

以分组的形式绑定对象数据

通过ng-option指令属性值,采用...as...group by for..in...

<body>
        <form name="temp_form" ng-controller = "testController">
            <div>学制:
                <select ng-model = "a" ng-options = "v.id as v.name for v in a_data" ng-change="a_change(a)">
                    <option value="">--请选择--</option>
                </select>
                <span>{{a_show}}</span>
            </div>
            <div>
                班级:
                <select ng-model="b" ng-options="v.id as v.name group by v.grade for v in b_data" ng-change="b_change(b)">
                    <option value="">--请选择--</option>
                </select>
                <span>{{b_show}}</span>
            </div>
        </form>
        <div>{{8.8  | number:1 | currency}}</div>
        <script type="application/javascript">
        var con = angular.module('main',[]);
        con.controller('testController',['$scope',function($scope){
            $scope.a_data=[
            {id:"1001",name:"小学"},
            {id:"1002",name:"初中"},
            {id:"1003",name:"大学"}
            ];
            $scope.b_data=[
            {id:"1001",name:"(1)班",grade:"一年级"},
            {id:"1002",name:"(2)班",grade:"二年级"},
            {id:"2001",name:"(1)班",grade:"一年级"},
            {id:"2002",name:"(2)班",grade:"二年级"},
            {id:"3001",name:"(1)班",grade:"一年级"},
            {id:"3002",name:"(2)班",grade:"二年级"}
            ];
            $scope.a = "";
            $scope.b = "";
            $scope.a_change = function(a){
                $scope.a_show = "you selected is " + a;
                console.info("you selected is " + a);
            }
            $scope.b_change = function(b){
                $scope.b_show = "you selected is " + b;
                console.info("you selected is " + b);
            }
        }])
    </script>
    </body>

 8.过滤器

  过滤器的主要功能是格式化数据,这里所说的数据包括视图模板中的表达式,也包括控制器中的数组和对象.

  过滤器的三种调用方式:

  1.单个过滤器

    {{}}双括号为表达式标记,在括号中 | 为管道符,通过该符号分为前后两部分,前部分为表达式,后部分为过滤器名称

  

<div>{{8.8  | number:1 | currency}}</div>

  number过滤器要放在currency过滤器前边,原因大家懂得

  2.多个过滤器

  {{表达式 | 过滤器1 | 过滤器2 | ...}}

  3.带参数的过滤器

  {{表达式 | 过滤器1 :参数1 : 参数2}}

  currency:货币过滤器
  number:四舍五入小数点个数过滤器

  排序方式过滤:

$scope.data = [
   {name:"张晓明",sex:"男",age:"24",score:95}
]
<li ng-repeat="stu in data | orderBy:'-score' | limitTo:3" ng-class-odd="'odd'" ng-class-even="'even'"></li>

   匹配方式过滤:

  {{数据 | filter:'匹配字符'}},一旦添加该参数,将在整个数据的属性中查找匹配项,找到后则显示,找不到则不显示,字符内容必须加引号

  {{data | filter:80}},在data数据的各个属性中查找包含"80"内容的记录

  在字符参数中使用对象形式匹配指定属性的数据:

  如果在过滤数据时已经确定了数据匹配的属性范围,可以在字符参数中通过对象的形式指定匹配的属性名称,如下

  {{数据 | filter:对象}}

  上述调用格式的对象中,过滤器参数是一个对象,这个对象通过key/value方式声明属性名称和匹配的字符内容,如果属性名称为$,则表示在全部的属性中查找,如下

  {{data | filter:{score:80}}}    {{data | filter:{$:80}}}

  后者相当于{{data | filter:80}}

  在字符参数中使用自定义函数匹配相应数据:

  {{数据 | filter:函数名称}}

  参数默认传递循环过程中的当前元素

<div>
            <ul>
                <li>
                    <span>序号</span>
                    <span>姓名</span>
                    <span>性别</span>
                    <span>年龄</span>
                    <span>分数</span>
                </li>
                <li ng-repeat="stu in data | filter:findscore" ng-class-odd="'odd'" ng-class-even="'even'">
                    <span>{{$index + 1}}</span>
                    <span>{{stu.name}}</span>
                    <span>{{stu.sex}}</span>
                    <span>{{stu.age}}</span>
                    <span>{{stu.score}}</span>
                </li>
            </ul>
        </div>
var con = angular.module('main',[]);
        con.controller('testController',['$scope',function($scope){
            $scope.a_data=[
            {id:"1001",name:"小学"},
            {id:"1002",name:"初中"},
            {id:"1003",name:"大学"}
            ];
            $scope.b_data=[
            {id:"1001",name:"(1)班",grade:"一年级"},
            {id:"1002",name:"(2)班",grade:"二年级"},
            {id:"2001",name:"(1)班",grade:"一年级"},
            {id:"2002",name:"(2)班",grade:"二年级"},
            {id:"3001",name:"(1)班",grade:"一年级"},
            {id:"3002",name:"(2)班",grade:"二年级"}
            ];
            $scope.data = [
                {name:"张晓明",sex:"",age:"24",score:95},
                {name:"李晓东",sex:"",age:"25",score:80},
                {name:"马晓华",sex:"",age:"30",score:85},
                {name:"师小婕",sex:"",age:"23",score:100}
            ];
            $scope.findscore = function (e){
                return e.score >80 && e.score < 100;
            }

  自定义过滤器:

    在页面模块中注册一个过滤器的构造方法,改方法将返回一个以输入值为首个参数的函数,在函数体中实现过滤器功能.而输入值为默认的被传入过滤器的对象.

    

<ul>
                <li>
                    <span>序号</span>
                    <span>姓名</span>
                    <span>性别</span>
                    <span>年龄</span>
                    <span>分数</span>
                </li>
                <li ng-repeat="stu in data | young:0" ng-class-odd="'odd'" ng-class-even="'even'">
                    <span>{{$index + 1}}</span>
                    <span>{{stu.name}}</span>
                    <span>{{stu.sex}}</span>
                    <span>{{stu.age}}</span>
                    <span>{{stu.score}}</span>
                </li>
            </ul>
con.filter('young',function(){
            return function(e,type){
                var _out = [];
                var _sex = type ? "" : "";
                for(var i = 0; i < e.length; i++){
                    if(e[i].age > 22 && e[i].age < 30 && e[i].sex == _sex){
                        _out.push(e[i]);
                    }
                }
                return _out;
            }
        })

过滤器默认传入参数e,代表当前元素.在自定义过滤器中,当前元素代表整个集合对象,在自定义函数过滤器中当前元素为整个结合对象中的当前循环元素.

返回以输入值(被过滤值)为首个参数的函数,通过return返回一个函数,参数e为在调用过滤器时,会被过滤的数据自动注入的,其他参数为过滤器传入的自定义参数,通过冒号向过滤器传递,先定义返回值,在做逻辑处理.

表头排序:

<ul>
                <li>
                    <span>序号</span>
                    <span  ng-click="title='name';desc = !desc">姓名</span>
                    <span ng-click="title='sex';desc = !desc">性别</span>
                    <span ng-click="title='age';desc = !desc">年龄</span>
                    <span ng-click="title='score';desc = !desc">分数</span>
                </li>
                <li ng-repeat="stu in data | orderBy:title:desc" ng-class-odd="'odd'" ng-class-even="'even'">
                    <span>{{$index + 1}}</span>
                    <span>{{stu.name}}</span>
                    <span>{{stu.sex}}</span>
                    <span>{{stu.age}}</span>
                    <span>{{stu.score}}</span>
                </li>
            </ul>
        </div>
con.controller('testController',['$scope',function($scope){
            $scope.desc = 0;
            $scope.title = "name";

 

 

确定controller作用域后,controller为变量初始化,这个时候变量已经被赋值,函数变量会被初始化,但是不会执行函数.

orderBy过滤器带有两个参数,第一个参数指定排序的属性名,第二个参数指定排序的方向,该值默认或缺省时为升序,1为降序,0为升序.

字符查找:

 

<li ng-repeat="stu in data | filter : {name:key}" ng-class-odd="'odd'" ng-class-even="'even'">
$scope.key = ' ';
{name:"师小婕 ",sex:"",age:"23",score:100}

name引号可有可无.

9.作用域:

作用域能存储数据模型,为表达式提供上下文环境和监听表达式变化并传播事件,它是页面视图和控制器之间的重要桥梁.

提供了$watch方法来监听数据模型的变化,ng-model实现双向数据绑定就是通过该方法进行数据模型的监听.

提供了$apply方法为各种类型的数据模型改变提供支撑,例如通过视图模板中的ng-click来执行控制器中的代码.

提供了执行环境,一个表达式必须在拥有该表达式属性的作用域中执行,作用域通过提供$scope对象,使所有的表达式对象都拥有执行环境.

$watch:

<div>
            <div>
                <input type="text" ng-model = "name" placeholder="please input you name" />
            </div>
            <div>累计变化次数:{{count}}</div>
        </div>
$scope.count = 0;
            $scope.name = '';
            $scope.$watch('name',function(){
                $scope.count ++;
            })

需要注意的是第一次加载时初始化过程中也是认为该值是改变的undefined--初始化,该方法也会执行.

作为数据模型的作用域:

作用域是控制器和视图的桥梁,同时作用域也是指令和视图的桥梁,无论是指令,还是控制器他们都可以通过作用域与视图中的DOM进行绑定.两条数据关系链

指令->作用域->视图      控制器->作用域->视图

作用域的层级和事件:

子级作用域可以继承父级作用域中的全部属性和方法,同级别子作用域不可以相互访问各自的属性和方法.

 引入作用域

con.controller('testController',['$scope',function($scope){

作用域事件传播:

两种方式可以实现作用域间的通信

  服务(service):

  事件(event):

     Angular中提供的两个方法:$broadcasted,$emitted

     $broadcasted:将事件从父级作用域传播到子级作用域

     $broadcasted(eventname,data) data为事件传播过程中携带的数据信息.

       $emitted:将事件从子级作用域传播到父级作用域

     $emitted(eventname,data)

  除了这两个传播事件的方法外,还需要调用$on方法,在作用域中监控传播来的事件,并获取相应的数据.$on(eventname,function(event,data){接收传播事件的处理方法})

  在一个作用域中定义事件的传播,然后在其他作用域中通过$on方法监控事件传播的状态.

不同controller的作用域不同,通过调用作用域中的函数,并定义事件的传播,在其他的作用域中监听事件传播.
controller1
                     $scope.to_patient = function(){
                $scope.$emit('event_1',"事件来源于子级")
            }
            $scope.to_child = function(){
                $scope.$broadcast('event_2',"事件来源于父级")
            }
controller2
            $scope.$on('event_1',function(event,data){
                ...
            })                

在监听函数中通过event下边相关方法操作被监听的域中的相关操作

10.依赖注入:

依赖注入原理:

var myApp = angular.module('myapp',[]);
            myApp.controller('ctl',['$scope',function($scope){
                
            }])
myApp.config(function($controllerProvider){
                $controllerProvider.register('ctl',['$scope'.Function($scope){
                    
                }])
            })

第一段代码为常用代码,第一段代码在Angular中执行的本质其实是第二段代码.

11.angular中mvc模式:

模板跳转:

<a href="#view/{{stu.stuId}}>{{stu.stuName}}</a>

$routeProvider.when('/view/:id',{

controller:'ctl',

templateUrl:'aa.html',

publicAccess:true

})

myApp.controller('ctl',function($scope,$routeParams){

for(var i = 0;i<students.length;i++){

  if(students[i].stuId == $routeParams.id){

  $scope.student = students[i]; 

  }

}

})

12. Angular 的服务

在Angular中服务是一种单利对象,服务的主要功能是为实现应用的功能提供数据和对象.按照功能不同,分为内置和自定义的服务.

内置服务如:$scope,$http,$windows,$location

$location:

获取当前地址栏中完整的url地址.

myApp.controller('ctl1',function($scope,$location){
                $scope.clicked = function(){
                    $scope.url = $location.absUrl();
                }
            })

自定义服务:

只需将服务注入到需要服务的容器中(控制器,指令,或其他自定义服务)就可以采用对象的方式调用服务中的属性和方法

定义服务的方法主要包含两种,一种是使用内置的$provider服务,一种是调用模块中的服务注册方法,如factory,service,constant,value等方法

添加自定义服务依赖选项方法:

隐式声明:指的是在创建服务的函数中,直接在参数中调用,不进行任何声明,如果对代码进行压缩时,注入的对象可能失效

app.factory('serviceName',function(dep1,dep2){});

调用$inject属性:将需要注入服务的各种对象包装成一个数组,并将它们作为$inject属性值,但是执行效率很低,不推荐

sf表示服务执行的函数

var sf = functioin(dep1,dep2){};
sf.$inject = ['dep1','dep2'];
app.factory('ServiceName',sf);

显示声明:指的是在创建服务的函数中,添加一个数组,在数组中顺序声明需要注入的服务或对象名称,高效,不丢代码,推荐使用,参数中的名称和声明可以不一样但是顺序必须一样

app.factory('serviceName',['dep1','dep2',function(dep1,dep2){}]);

&& 通过指令在ng-repeat中动态添加删除class

<li  ng-repeat="stu in data | filter : {name:key}" ng-class-odd="'odd'" ng-class-even="'even'">
                    <span repeat-my >{{$index + 1}}</span>
                    <span repeat-my>{{stu.name}}</span>
                    <span repeat-my>{{stu.sex}}</span>
                    <span repeat-my>{{stu.age}}</span>
                    <span repeat-my>{{stu.score}}</span>
                </li>
con.directive("repeatMy",function(){
            return {
                restrict:"A",
                link:function(scope,elem,attrs){
                    elem.bind('click',function(){
                        var test = attrs.$$element[0];
                        console.info(test.getAttribute('class').indexOf('ok'))
                        if(test.getAttribute('class').indexOf('ok') > 0){
                            elem.removeClass("ok");
                        }else{
                            elem.addClass("ok");
                        }
                    })
                }
            }
        })

 13. $apply Scope提供$apply方法传播Model的变化

 什么时候使用$apply()方法呢?情况非常少,实际上几乎我们所有的代码都包在scope.apply()里面,像ng−click,controller的初始化,http的回调函数等。在这些情况下,我们不需要自己调用,实际上我们也不能自己调用,否则在apply()方法里面再调用apply()方法会抛出错误。如果我们需要在一个新的执行序列中运行代码时才真正需要用到它,而且当且仅当这个新的执行序列不是被angular JS的库的方法创建的,这个时候我们需要将代码用scope.apply()包起来。下面用一个例子解释:

<div ng:app ng-controller="Ctrl">{{message}}</div>

functionCtrl($scope) {
  $scope.message ="Waiting 2000ms for update";   
  setTimeout(function () {
    $scope.message ="Timeout called!";
     // AngularJS unaware of update to $scope
  }, 2000);
}

     上面的代码执行后页面上会显示:Waiting 2000ms for update。显然数据的更新没有被angular JS觉察到。
     接下来,我们将Javascript的代码稍作修改,用scope.apply()包起来。


functionCtrl($scope) {
  $scope.message ="Waiting 2000ms for update";
  setTimeout(function () {
    $scope.$apply(function () {
       $scope.message ="Timeout called!";
      });
  }, 2000);
}

     这次与之前不同的是,页面上先会显示:Waiting 2000ms for update,等待2秒后内容会被更改为:Timeout called! 。显然数据的更新被angular JS觉察到了。
     NOTE:我们不应该这样做,而是用angular JS提供的timeout方法,这样它就会被自动用apply方法包起来了。

科学是把双刃剑
     最后,我们再来瞅一眼scope.apply()和scope.apply(function)方法吧!虽然angular JS为我们做了很多事情,但是我们也因此丢失了一些机会。从下面的伪代码一看便知:

function$apply(expr) {
  try {
    return$eval(expr);
  } catch(e) {
    $exceptionHandler(e);
  } finally {
    $root.$digest();
  }
}

  它会捕获所有的异常并且不会再抛出来,最后都会调用$digest()方法。

总结一下

  $apply()方法可以在angular框架之外执行angular JS的表达式,例如:DOM事件、setTimeout、XHR或其他第三方的库。这仅仅是个开始,水还有很深,欢迎大家一起来deep dive!

 14.scope.$watch

 

$watch(watchFn,watchAction,deepWatch)

 

watchFn:angular表达式或函数的字符串

 

watchAction(newValue,oldValue,scope):watchFn发生变化会被调用

 

deepWatch:可选的布尔值命令检查被监控的对象的每个属性是否发生变化

 

$watch会返回一个函数,想要注销这个watch可以使用函数

 

scope.$watch(
        function () {
          return scope.$eval(attrs.bfAssertSameAs);
        },
        function () {
          ngModel.$setValidity('same', isSame(ngModel.$modelValue));
        }
      );
var firstController = function ($scope){
    $scope.name='张三';
     
    $scope.count=0;
     
    // 监听一个model 当一个model每次改变时 都会触发第2个函数
    $scope.$watch('name',function(newValue,oldValue){
 
        ++$scope.count;
 
        if($scope.count > 30){
            $scope.name = '已经大于30次了';
        }
    });
 
}

 15.通过指令获取元素的值,以及作用域中的其他值

16.页面追加元素

angular.module("com.ngnice.app").directive('bfFieldError', function bfFieldError($compile){
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel){
            var subScope = scope.$new(true);
            subScope.hasError = function(){
                return ngModel.$invalid && ngModel.$dirty;
            };
            subScope.errors = function(){
                return ngModel.$error;
            };
            var hint = $compile('<ul class="" ng-if="hasError()"><li ng-repeat="(name,wrong) in errors()" ng-if="wrong">{{name | error}}</li></ul>')(subScope);
            element.after(hint);
        }
    };
});

 17. 删除数组元素

$scope.array.splice($.inArray(id, $scope.array), 1);

 18. 按钮变换,焦点获取

<tbody>
                <tr ng-repeat="cor in cors">

                    <td>{{$index + 1}}</td>
                    <td>{{cor.mistake}}</td>
                    <td style="padding: 0px 0px;">
                        <input type="text" name="correction" class="form-control" ng-model="cor.correction" readonly/>
                    </td>
                    <td>{{cor.operator}}</td>
                    <td>{{cor.updatetime | date:'yyyy-MM-dd hh:mm:ss'}}</td>
                    <td>
                        <a href="javascript:void(0)" class="operate_a" ng-click="editSec($event,cor.id,cor.correction)">编辑</a>
                        <a href="javascript:void(0)" class="operate_a" ng-click="deleteCor(cor.id)">删除</a>
                    </td>
                </tr>
                </tbody>
$scope.editSec = function (event,id,context) {
        if(angular.element(event.target).context.innerHTML == "编辑"){
            angular.element(event.target).parents("tbody").find("input").attr("readonly","readonly");
            angular.forEach(angular.element(event.target).parents("tbody").find("input"),function (data, index, array) {
                angular.element(angular.element(data).parents("tr").find("a")[0]).context.innerHTML = "编辑";
            })
            $scope.checkEdit = false;
            angular.element(event.target).parents("tr").find("input").removeAttr('readonly').focus();
            angular.element(event.target).context.innerHTML = "保存";

        }else{
            $scope.updateCor(id,context);
            $scope.checkEdit = true;
            angular.element(event.target).parents("tr").find("input").attr("readonly","readonly");
            angular.element(event.target).context.innerHTML = "编辑";

        }

    }

 

posted @ 2017-03-21 13:25  yangfei969  阅读(666)  评论(0编辑  收藏  举报