AngularJS 学习笔记(2)

观看angularJS视频教程做了如下笔记:

1. 简介

1. $scope 里的$apply $digest 方法
scope 是一个指向应用model的object,也是表达式的执行 上下文。
scope 被放置于一个类似应用的DOM结构的层次结构中。

  • angular是怎么知道变量发生了改变:

要知道一个变量变了,方法不外乎两种:
1.能通过固定的接口才能改变变量的值,比如说只能通过set()设置变量值,set被调用时比较一下就知道了。
2.脏检查,将元对象复制一份快照,在某个时间,比较现在对象与快照的值,如果不一样就表明发生变化,这个策略要保留两份变量,而且要遍历对象,比较每个属性,这样会有一定性能问题。

angular的策略

angular的实现是使用脏检查。
1.不会脏检查所有对象,当对象被绑定到html中,这个对象添加为检查对象(watcher)。
2.不会脏检查所有属性,同样当属性呗绑定后,这个属性被列为检查的属性。
在angular程序初始化时,会将绑定的对象的属性添加为监听对象(watcher),也就是说一个对象绑定了n个属性,就会添加n个watcher。

  • 什么时候去脏检查

angular所系统的方法中都会触发比较事件,比如:controller初始化的时候,所有已ng-开头的事件执行后,都会触发脏检查。

  • 如何手动触发脏检查

$apply 仅仅只是进入angular context,然后通过$digest 去触发脏检查。
$apply 如果不给参数的话,会检查改$scope 里的所有监听的属性,推荐给上参数。

  • $digest()

所属的scope 和其所有子scope 的脏检查,脏检查又会触发$watch() ,整个angular双向绑定机制就活了起来。
不建议直接调用$digest() ,而应该使用$apply() , $apply() 其实不能把信直接送给$digest ,之间还有$eval 门卫把关,如果$apply 带的表达式不合法,$eval 会把错误送交$exceptionHandler。合法才触发digest,所以更安全。

在angular.js框架文件中如何编写$apply

$apply: function (a) {
         try {
              n("$apply");
              try {
                  return this.$eval(a)
              } finally {
                  J.$$phase = null
              }
          } catch (b) {
              f(b)
          } finally {
              try {
                  J.$digest()
              } catch (c) {
                  throw f(c), c;
              }
          }
}

例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$apply</title>
</head>
<body ng-app="myApp" ng-controller="MyCtrl">
<h1>{{date}}</h1>
<script src="js/angular-1.5.8.min.js"></script>
<script>
    angular.module('myApp',[])
            .controller('MyCtrl',function($scope){
                $scope.date=new Date();
                setInterval(function(){
                    //可以触发脏检查
                    $scope.$apply(function(){
                        $scope.date=new Date();
                    });
                },1000);
            });
</script>
</body>
</html>

2. $scope 里的$watch 方法

$digest执行时,如果watch观察的value与上次执行时不一样时,就会被触发。

AngularJS内部的watch实现了页面随吗,model的及时更新。

$watch(watchFn,watchAction,deepWatch)
watchFn:angular表达式或函数的字符串。
watchAction(newValue,oldValue,scope):watchFn发生辩护会被调用。
deepWatch:可选的布尔值命令,检查被监控的对象的每个属性是否发生变化。

例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$watch</title>
</head>
<body ng-app="myApp" ng-controller="MyCtrl">
<input type="text" ng-model="name">
<p>{{name}},改变了{{count}}次</p>
<script src="js/angular-1.5.8.min.js"></script>
<script>
    angular.module('myApp',[])
            .controller('MyCtrl',function($scope){
                $scope.name='张三';
                $scope.count=0;
                $scope.data={
                    name:'李四',
                    count:20
                };
                //监听一个model,当model每次改变时,都会触发这个函数
                $scope.$watch('name',function(newValue,oldValue){
                    ++$scope.count;
                    if($scope.count>10){
                        $scope.name='已经大于10次了';
                    }
                });
                //true:监听整个data对象和其属性。false:只监听data对象
                $scope.$watch('data',function(){

                },true);
            });
</script> 
</body>
</html>

2. 购物车案例

1.forEach()
angular有自己的生命周期。循环给一个 angular监听的变量复值时。最好还是用angular自带的循环方法。angular.forEach()

var objs =[{a:1},{a:2}];
angular.forEach(objs, function(data,index,array){
//data等价于array[index]
console.log(data.a+'='+array[index].a);
});

参数如下:
objs:需要遍历的集合
data:遍历时当前的数据
index:遍历时当前索引
array:需要遍历的集合,每次遍历时都会把objs原样的传一次。

也可以不用写后面两个参数:

var objs =[{a:1},{a:2}];
angular.forEach(objs, function(data){
console.log(data.a);
});

例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body ng-app="myCart" ng-controller="CartCtrl">
<div class="container">
    <table class="table table-hover">
        <thead>
            <tr>
                <td>编号</td>
                <td>名称</td>
                <td>数量</td>
                <td>单价</td>
                <td>总价</td>
                <td>操作</td>
            </tr>
        </thead>
        <tbody  ng-hide="!cart.length">
            <tr ng-repeat="item in cart">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>
                    <button type="button" class="btn btn-primary" ng-click="reduce(item.id)">-</button>
                    <input type="text" value="" ng-model="item.num" readonly>
                    <button type="button" class="btn btn-primary" ng-click="add(item.id)">+</button>
                </td>
                <td>{{item.price}}</td>
                <td>{{item.num*item.price}}</td>
                <td>
                    <button type="button" class="btn btn-danger" ng-click="remove(item.id)">移除</button>
                </td>
            </tr>
            <tr>
                <td></td>
                <td>总数量:</td>
                <td>{{totalNum()}}</td>
                <td>总价格:</td>
                <td>{{totalPrice()}}</td>
                <td>
                    <button type="button" class="btn btn-danger" ng-click="cart={}">清空购物车</button>
                </td>
            </tr>
        </tbody>
    </table>
    <p ng-show="!cart.length">购物车为空,快来添加产品吧~</p>
</div>
<script src="js/angular-1.5.8.min.js"></script>
<script src="js/cart.js"></script>
</body>
</html>
//cart.js
angular.module('myCart',[])
    .controller('CartCtrl',function($scope){
        $scope.cart=[
            {
                id:1,
                name:'iphone6',
                num:20,
                price:500
            },
            {
                id:2,
                name:'iphone6S',
                num:32,
                price:1500
            },
            {
                id:3,
                name:'iphone7',
                num:43,
                price:2500
            },
            {
                id:4,
                name:'iphone7S',
                num:46,
                price:3500
            }
        ];
        //总价格
        $scope.totalPrice=function(){
            var totalPrice=0;
            angular.forEach($scope.cart,function(item){
                totalPrice+=item.num*item.price;
            });
            return totalPrice;
        };
        //总数量
        $scope.totalNum=function(){
            var totalNum=0;
            angular.forEach($scope.cart,function(item){
                totalNum+=parseInt(item.num);
            });
            return totalNum;
        };
        //找到操作的索引
        var findIndex=function(id){
            var index=-1;
            angular.forEach($scope.cart,function(item,key){
                if(item.id===id){
                    index=key;
                }
            });
            return index;
        };
        //移除产品
        $scope.remove=function(id){
            var index=findIndex(id);
            if(index!==-1){
                $scope.cart.splice(index,1);
            }
        };
        //增加产品数量
        $scope.add=function(id){
            var index=findIndex(id);
            if(index!==-1){
                ++$scope.cart[index].num;
            }
        };
        //减少产品数量
        $scope.reduce=function(id){
            var index=findIndex(id);
            if(index!==-1){
                var _num=$scope.cart[index].num;
                if(_num>1){
                    --$scope.cart[index].num;
                }else {
                    if(confirm('是否移除该产品?')){
                        $scope.remove(id);
                    }
                }
            }
        };
    });

运行结果为:
购物车demo结果

3. 模块和控制器、过滤器

1. 模块和控制器

  • 什么是Module?

大部分应用都有一个主方法(main)用来实例化、组织、启动应用。
AngularJS应用没有主方法,而是使用模块来声明应用应该如何启动。
模块允许通过声明的方法来描述应用中的依赖关系,以及如何进行组装和启动。

  • Angular模块

模块是组织业务的一个框框,在一个模块当中定义多个服务。当引入了一个模块的时候,就可以使用这个模块提供的一种或多种服务了。
AngularJS本身的一个默认模块叫做ng,它提供了$http,$scope 等等服务。
服务只是模块提供的多种机制中的一种,其他的还有指令(directive),过滤器(filter),及其他配置信息。
也可以在已有的模块中新定义一个服务,也可以先定义一个模块,然后在新模块中定义新服务。
服务是需要显示地声明依赖(引入)关系的,让ng自动地做注入。

  • Module优点

启动过程是声明式的,更容易懂。
在单元测试是不需要加载全部模块的,因此这种方式有助于写单元测试。
可以在特定情况的测试中增加额外的模块,这些模块能更改配置,能帮助进行端对端的测试。
第三方代码可以作为可复用的module打包到angular中。
模块可以以任何先后或者并行的顺序加载(因为模块的执行本身是延迟的)。

  • 定义模块

angular.module(name,[requires],configFn);
name:模块的名称。
[requires]:需要引入的其他模块名称。
configFn:会在模块初始化时执行,可以配置模块的服务。

2. $provideprovider() 方法

服务本身是一个任意的对象。
ng提供服务的过程涉及到angular的依赖注入机制。
angular是用$provide 对象来实现自动依赖注入机制,注入机制通过调用一个provider的$get() 方法,把得到的对象作为参数进行相关调用。
$provide.provider 是一种定义服务的方法,$provide 还提供了很多很简便的方法,这些简便的方法还直接被module所引用。

例子(不常用):

var myApp=angular.module('myApp',[],function($provide){
    $provide.provider('CustomService',function(){
        this.$get=function(){
            return{
                message:'CustomService Message'
            }
        }
    })
});

3. $provide里的factory、service方法

$provide.factory
factory方法直接把一个函数当成是一个对象的$get() 方法。
返回的内容可以使任意类型

$provide.service
和factory类似,但返回的必须是对象。

4. 多个控制器内数据共享

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多个控制器共享数据</title>
</head>
<body>
<div ng-app="myApp">
    <div ng-controller="firstCtrl">
        first.data<input type="text" ng-model="data.name">
        first.Data<input type="text" ng-model="Data.message">
        <p>first-name:{{data.name}}</p>
        <p>first-message:{{Data.message}}</p>
    </div>
    <div ng-controller="nextCtrl">
        <p>next-name:{{data.name}}</p>
        <p>next-message:{{Data.message}}</p>
    </div>
</div>
<script src="js/angular-1.5.8.min.js"></script>
<script>
    angular.module('myApp',[])
            .factory('Data',function(){
                return{
                    message:'共享的数据'
                }
            })
            .controller('firstCtrl',function($scope,Data){
                $scope.data={
                    name:'张三'
                };
                $scope.Data=Data;
            })
            .controller('nextCtrl',function($scope,Data){
                $scope.data=$scope.$$prevSibling.data;//$$prevSibling通过当前作用域找到上一个作用域
                $scope.Data=Data;
            });
</script>
</body>
</html>

5. 过滤器current number data

  • 什么是angular过滤器

是用于数据的格式化,或者筛选的函数,可以直接在模板中通过一种语法使用。
{{expression | filter}}
{{expression | filter1 | filter2}}
{{expression | filter1:param,...}}

  • 筛选器:
    1. number:为数字添加分隔”,”,会更方便显示数字,如果加上数字参数,可以控制保留小数的个数。
    2. currency:货币格式,默认为$,可以通过加参数来改变单位。
    3. date:格式化时间,添加不同的参数可以有不同格式显示时间。查看详情
    4. limitTo:添加数字参数,将数组切割为所添参数个数的数组,如参数为负数可获取倒数参数个数的数组。
    5. lowercase:将英文格式化为小写格式。
    6. uppercase:将英文格式化为大写格式。
    7. filter:添加参数,从数组项中查找一个子集。
    8. orderBy:排序。
    9. json:格式化为json格式。一般用于调试。

6. 控制器的合理使用、显示、隐示的依赖注入

  • 正确的使用controller

    1. controller不应该尝试做太多的事情。他应仅仅包含单个视图所需要的业务逻辑。
    2. 保持controller的简单性,常见办法是抽出那些不属于controller的工作到service中,在controller通过依赖注入来使用这次service。
    3. 不要在controller中做以下的事情
      1) 任何类型的DOM操作 - controller应该仅仅包含业务逻辑,任何表现逻辑放到controller中,大大地影响了应用逻辑的可测试性。angular为了自动操作(更新)DOM,提供的数据绑定。如果希望执行我们自定义的DOM操作,可以把表现逻辑抽取到directive中。
      2) Input formatting(输入格式化) - 使用angular form cocntols代替。
      3) Output filtering(输出格式化过滤) - 使用angular filters代替。
      4) 执行无状态或有状态的、controller共享的代码 - 使用angular server代替。
      5) 实例化或者管理其他组件的生命周期(例如创建一个服务实例) - 使用模块代替。
//隐示的依赖注入
.controller('firstCtrl',function($scope){...});
//显示的依赖注入(推荐使用)
.controller('nextCtrl',['$scope',function($scope){...}]);
//controller方法如何依赖注入
function otherCtrl(a){...}
otherCtrl.$inject=['$scope'];

4. 内置渲染指令、自定义指令

  • 什么是指令

可以利用指令来扩展HTML标签,增加声明式语法来实现想做的任何事,可以对应用有特殊意义的元素和属性来替换一般的HTML标签。

1. 渲染指令

ng-init :初始化数据
ng-bind :绑定数据
ng-repeat
ng-include:添加地址参数,调用另一个静态页
ng-bind-template :绑定模板

2. 内置事件指令

ng-change
ng-click
ng-dbclick
ng-mousedown
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
ng-mouseup
ng-submit

3. 内置节点指令

  1. ng-style:先在控制器中定义一个样式: $scope.defaultStyle={color:'red','margin-top':'50px'};再应用在页面上:<div ng-style="defaultStyle">
  2. ng-class:当表达式为真时添加某个class。例: ng-class="{ red:status }",当status为真时,为元素添加red类,为假时去掉red类
  3. ng-class-even:当前行是偶数行时添加某个class。例:ng-class-even="'evenRow'"
  4. ng-class-odd:当前行是奇数行是添加某个calss 。 例: ng-class-odd="'oddRow'"
  5. ng-show:为真时显示。例:<div ng-show="status">status为真时显示</div>
  6. ng-hide:为真时隐藏。
  7. ng-switch:选择表达式。例子:
<ul ng-switch on="status">
   <li ng-switch-when="true">
       true
   </li>
   <li ng-switch-when="false">
       false
   </li>
</ul>
  1. ng-src:表达式作为图片url,例:<img ng-src="{{src}}">
  2. ng-href:表达式作为url
  3. ng-if:为真时显示:<div ng-if="status">为真时显示</div>

注:所有ng-指令里,除变量外的所有字符串都必须加单引号”

5. 表单、自定义表单

  • 一般来讲表单可能遇到的问题:

    1. 如何数据绑定
    2. 验证表单
    3. 显示出错信息
    4. 整个form的验证
    5. 避免提交没有验证吐过的表单
    6. 防止多次提交
  • Form控制变量

    1. 字段是否未更改:formName.inputFieldName.$pristine
    2. 字段是否更改:formName.inputFieldName.$dirty
    3. 字段有效:formName.inputFieldName.valid
    4. 字段无效:formName.inputFieldName.$invalid
    5. 字段错误信息:formName.inputFieldName.$error
  • input属性

    1. name:名字
    2. ng-model:绑定的数据
    3. ng-required:是否必填
    4. ng-minlength:最小长度
    5. ng-maxlength:最大长度
    6. ng-pattern:匹配模式
    7. ng-change:值变化时的回调
  • Form方法

$setPristine 将表单复位原始状态,class,$dirty,$spristine

例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表单验证</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<div ng-app="myApp" style="margin-top: 50px;">
    <form name="myForm" ng-controller="myCtrl" class="container form-horizontal" action="register.php" method="post">
        <!-- 用户名 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">用户名</label>
            <div class="col-sm-10" ng-class="{'has-error':myForm.username.$invalid && myForm.username.$dirty && myForm.username.$pristine}">
                <input type="text" name="username" autocomplete="off" ng-model="data.username" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="用户名">
                <div ng-show="myForm.username.$error.maxlength" class="alert alert-danger help-block">用户名长度不能超过10位</div>
                <div ng-show="myForm.username.$error.minlength" class="alert alert-danger help-block">用户名长度不能小于5位</div>
                <div ng-show="myForm.username.$error.pattern" class="alert alert-danger help-block">用户名必须为英文字母开始</div>
            </div>
        </div>
        <!-- 密码 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">密码</label>
            <div class="col-sm-10" ng-class="{'has-error':myForm.psd.$invalid && myForm.psd.$dirty && myForm.username.$pristine}">
                <input type="password" name="psd" autocomplete="off" ng-model="data.psd" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="密码">
                <div ng-show="myForm.psd.$error.maxlength" class="alert alert-danger help-block">用户名长度不能超过10位</div>
                <div ng-show="myForm.psd.$error.minlength" class="alert alert-danger help-block">用户名长度不能小于5位</div>
                <div ng-show="myForm.psd.$error.pattern" class="alert alert-danger help-block">用户名必须为英文字母开始</div>
            </div>
        </div>
        <!-- 确认密码 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">确认密码</label>
            <div class="col-sm-10" ng-class="{'has-error':myForm.psdConfirm.$invalid && myForm.psdConfirm.$dirty && myForm.psdConfirm.$pristine}">
                <input type="password" name="psdConfirm" autocomplete="off" ng-model="data.psdConfirm" ng-required="true" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="确认密码">
                <div ng-show="myForm.psd.$dirty && myForm.psdConfirm.$dirty && data.psdConfirm!=data.psd" class="alert alert-danger help-block">两次密码不一致</div>
            </div>
        </div>
        <!-- 邮箱 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">邮箱</label>
            <div class="col-sm-10" ng-class="{'has-error':myForm.email.$invalid && myForm.email.$dirty && myForm.email.$pristine}">
                <input type="email" name="email" autocomplete="off" ng-model="data.email" ng-required="true" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="邮箱">
                <div ng-show="myForm.email.$error.email" class="alert alert-danger help-block">邮箱格式不正确</div>
            </div>
        </div>
        <!-- 网址 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">博客</label>
            <div class="col-sm-10" ng-class="{'has-error':myForm.blog.$invalid && myForm.blog.$dirty && myForm.blog.$pristine}">
                <input type="url" name="blog" autocomplete="off" ng-model="data.blog" ng-required="true" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="博客">
                <div ng-show="myForm.url.$error.url" class="alert alert-danger help-block">博客地址格式不正确</div>
            </div>
        </div>
        <!-- 年龄 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">年龄</label>
            <div class="col-sm-10" ng-class="{'has-error':myForm.age.$invalid && myForm.age.$dirty && myForm.age.$pristine}">
                <input type="number" name="age" autocomplete="off" ng-model="data.age" ng-required="true" min="10" max="99" class="form-control" placeholder="年龄">
                <div ng-show="myForm.age.$error.min" class="alert alert-danger help-block">年龄不能小于10岁</div>
                <div ng-show="myForm.age.$error.max" class="alert alert-danger help-block">年龄不能大于99岁</div>
            </div>
        </div>
        <!-- 性别 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">性别</label>
            <div class="col-sm-10">
                <label class="radio-inline">
                   <input type="radio" ng-required="true" name="sex" ng-model="data.sex" value="1"></label>
                <label class="radio-inline">
                    <input type="radio" name="sex" ng-model="data.sex" value="0"></label>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">爱好</label>
            <div class="col-sm-10">
                <label class="checkbox-inline" ng-repeat="hobby in hobbies">
                    <input type="checkbox" name="hobby[]" ng-checked="data.hobbies==undefined ? false:data.hobbies.indexOf(hobby.id)!==-1" ng-click="hobbySelect(hobby.id)"> {{hobby.name}}
                </label>
            </div>
        </div>
        <!-- 城市 -->
        <div class="form-group">
            <label class="col-sm-2 control-label">出生地</label>
            <div class="col-sm-3">
                <select class="form-control" ng-required="true" ng-change="data.area=false" ng-model="data.province" ng-options="x.id as x.name for x in cities | cityFilter:0"></select>
            </div>
            <div class="col-sm-3">
                <select class="form-control" ng-required="true"  ng-show="data.province" ng-model="data.area" ng-options="x.id as x.name for x in cities | cityFilter:data.province"></select>
            </div>
            <div class="col-sm-3">
                <select class="form-control" ng-required="true"  ng-show="data.province && data.area" ng-model="data.city" ng-options="x.id as x.name for x in cities | cityFilter:data.area"></select>
            </div>
        </div>
        <!-- 提交 -->
        <div class="form-group">
            <div class="col-sm-10 col-sm-offset-2">
                <button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid || data.hobbies===undefined || data.hobbies.length===0">注册</button>
                <button type="reset" class="btn btn-info" ng-click="reset()">重置</button>
            </div>
        </div>
    </form>
</div>
<script src="js/angular-1.5.8.min.js"></script>
<script src="js/form.js"></script>
</body>
</html>
//form.js
angular.module('myApp',[])
    //三级关联城市过滤器
    .filter('cityFilter',function(){
        return function (data,parent){
            var filterData=[];
            angular.forEach(data,function(obj){
                if(obj.parent===parent){
                    filterData.push(obj);
                }
            });
            return filterData;

        }
    })
    .controller('myCtrl',['$scope',function($scope){
        var that=this;
        $scope.hobbies=[
            {
                id:1,
                name:'跑步'
            },
            {
                id:2,
                name:'打台球'
            },
            {
                id:3,
                name:'打羽毛球'
            }
        ];
        $scope.cities=[
            {
                name:'上海',
                parent:0,
                id:1
            },
            {
                name:'上海市',
                parent:1,
                id:2
            },
            {
                name:'徐家汇',
                parent:2,
                id:8
            },
            {
                name:'徐汇区',
                parent:2,
                id:5
            },
            {
                name:'长宁区',
                parent:2,
                id:3
            },
            {
                name:'北京',
                parent:0,
                id:4
            },
            {
                name:'北京市',
                parent:4,
                id:5
            },
            {
                name:'东城区',
                parent:5,
                id:6
            },
            {
                name:'丰台区',
                parent:5,
                id:7
            },
            {
                name:'浙江',
                parent:0,
                id:9
            },
            {
                name:'杭州',
                parent:9,
                id:100
            },
            {
                name:'宁波',
                parent:100,
                id:66
            },
            {
                name:'西湖区',
                parent:100,
                id:35
            }
        ];
        $scope.data={
            hobbies:[1,2],
            city:66
        };
        //重置,先克隆原始数据
        $scope.origData=angular.copy($scope.data);//如果使用$scope.origData=$scope.data,那么data变化,origData也会变化
        $scope.reset=function(){
            $scope.data=angular.copy($scope.origData);//再将已经克隆的数据赋给data
            that.initCity();//重新调用城市
            $scope.myForm.$setPristine();//将表单复位为原始状态
        };
        //爱好
        $scope.hobbySelect=function(id){
            var index=-1;
            if($scope.data.hobbies==undefined){
                $scope.data.hobbies=[];
            }else {
                index=$scope.hobbies.indexOf(id);
            }
            if(index===-1){
                $scope.data.hobbies.push(id);
            }else{
                $scope.data.hobbies.splice(index,1);
            }
        };
        //让城市关联起来
        this.findCityId=function(parent){
            var parentId;
            angular.forEach($scope.cities,function(city){
                if(city.id===parent){
                    parentId=city.parent;
                }
            });
            return parentId;
        };
        //根据默认的城市查找前两级
        this.initCity=function(){
            if($scope.data.city!==undefined){
                $scope.data.area=this.findCityId($scope.data.city);
                $scope.data.province=this.findCityId($scope.data.area);
            }
        };
        this.initCity();
    }]);

6. ng-model

ng-model是angular原生的directive。
通过require ngModel可以更深入的去处理数据的双向绑定。

  • ngModel里的属性

    1. $parsers属性保存了从viewValue向modelValue绑定过程中的处理函数,它们将来会依次执行。
    2. $formattters它保存的是从modelValue向viewValue绑定过程中的处理函数。
    3. $setViewValue 当view发生了某件事情时,从view向model绑定调用$setViewValue 把viewValue保存下来。
    4. $render 当模型发生变化时,应该怎么去更新视图,从model向view绑定,调用ctrl.$render 方法,将viewValue渲染到页面上。
    5. $serValidity 设置验证结果。
    6. $viewValue 视图的值。  
    7. modelValue 模型里的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值