分享

Angular开发中的注意事项

 昨夜雾浓 2018-04-25

1. 页面元素的控制

1.1 调用element方法控制DOM元素

  使用Angular框架开发应用时,尽量不要直接通过Javascript代码直接操作DOM元素,也不要引入Jquery来操作DOM元素,而是通过Angular内部的jQLite来实现:
  angular.element()element

    <div ng-controller='myController' id='control'>
        <button ng-click='add()'>添加元素</button>
        <button ng-click='del()'>删除元素</button>
    </div>
    <script type="text/javascript">
        var app=angular.module('myapp',[]);
        app.controller('myController',['$compile','$scope',function($compile,$scope){
            $scope.hello='hello Angular!';
            $scope.log=function(){
                console.log('这是动态添加的方法!');
            };
            var html="<div ng-click='log()'>{{hello}}</div>";
            //生成一个Jquery对象
            var template=angular.element(html);
            //对生成的Jquery对象进行编译
            var newHtml=$compile(template)($scope);
            $scope.add=function(){
                angular.element(document.getElementById('control')).append(newHtml);
            }
            $scope.del=function(){
                if(newHtml){
                    newHtml.remove()
                }
            }
        }]);
    </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

  上述代码中,控制器中注入了$compile服务,目的是初始化相关的依赖,并对生成的Jquery对template进行编译,以便于调用append方法。

1.2 解决setTimeout改变属性的无效

  在Angular中,大部分操作之后的效果都由$apply方法自动在页面中完成,如果直接调用非Angular中的方法或函数,例如setTimeout方法,那么系统就不会调用$apply方法,导致方法执行失败。
  有两种方法可以解决:

  • 在setTimeout方法中,将执行的函数或表达式包含在$apply方法中
    setTimeout(function(){
    scope.apply(function(){
    $scope.tip=’欢迎来到Angular世界!’;
    })
    },1000)
  • 直接调用与setTimeout方法对应的$timeout服务
    $timeout(function(){
      $scope.tip=’欢迎来到Angular世界!’;
    },1000)

1.3 解决双大括号绑定元素时的闪烁问题

在Angular内部,可以向元素中添加ng-clock属性来实现元素的隐藏效果:
<div ng-clock>{{message}}</div>
如果是绑定纯文字的内容,建议使用ng-bind的方式,而非双大括号:
<div ng-bind="message"></div>

2. 使用ng-repeat时的注意事项

2.1

  1. 如果有过滤器,调用$index并不能准确定位到对应的记录。
    解决方案:使用其他的定位方式,例如元素的id等。
  2. 调用ng-repeat指令重新请求数据时,并不是在原来的DOM元素中更新数据,而是再次新建DOM元素。
    解决方案:使用track by排序ng-repeat中的数据:
    user in users track by user.id
  3. 在通过ng-repeat指令生成的子元素中,如果通过父元素的scope对象更新数据时,不能直接更新遍历的数据源,而必须逐个更新。

2.2 正确理解ng-repeat指令中的scope继承关系

  在调用ng-repeat 指令显示数据时,ng-repeat在新建DOM元素时,也为每个新建的DOM元素创建了独立的scope作用域。
  尽管如此,但它们的父级scope作用域是相同的,都是构建控制器时注入的$scope对象,调用angular.element(domElement).scope方法可以获取某个DOM元素所对应的作用域,通过某个DOM元素所对应的作用域又可以访问到他的父级作用域,从而修改绑定的数据源。

    <div ng-controller='myController'>
        <input type="button" value="按钮1" ng-click='change1()' />
        <input type="button" value="按钮2" ng-click='change2()' />
        <input type="button" value="按钮3" ng-click='change3()' />
        <ul>
            <li ng-repeat='user in users track by user.id'>
                <span id="spn{{user.id}}">{{user.id}}</span>
                <span>{{user.name}}</span>
                <span>{{user.score}}</span>
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        var app=angular.module('myapp',[]);
        app.controller('myController',['$scope',function($scope){
            $scope.users=[
                {id:1010,name:'zhangsan',score:10},
                {id:1020,name:'lisi',score:60},
                {id:1030,name:'wangwu',score:90}
            ];
            $scope.change1=function(){
                var scop1=angular.element(document.getElementById('spn1010')).scope();
                var scop2=angular.element(document.getElementById('spn1020')).scope();
                console.log(scop1==scop2);//false
            };
            $scope.change2=function(){
                var scope=angular.element(document.getElementById('spn1020')).scope();
                console.log(scope.$parent==$scope);//true
            };
            $scope.change3=function(){
                var scope=angular.element(document.getElementById('spn1030')).scope();
                scope.$parent.users=[
                    {id:1040,name:'wanger',score:'80'},
                    {id:1050,name:'zhaoliu',score:'900'}
                ];
            }
        }]);
    </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

3. 解决单击按钮事件中的冒泡现象

  与在Javascript中一样,都可以使用stopPropagation()方法,在Angular中:
  $event.stopPropagation()

4. 释放多余的$watch检测函数

  在Angular中,当$watch函数被调用时,将返回一个释放$watch绑定的unbind函数,因此,只需要再次调用这个$watch函数机具款有释放其检测功能。

    <div ng-controller='myController'>
        <input type="text" ng-model='content' />
        <div>第{{num}}次变化</div>
        <button ng-click='stopWatch()'>停止检测</button>
    </div>
    <script type="text/javascript">
        var app=angular.module('myapp',[]);
        app.controller('myController',['$scope',function($scope){
            $scope.num=0;
            $scope.stopWatch=function(){
                contentWatch();
            }
            var contentWatch=$scope.$watch('content',function(newVal,oldVal){
                //排序页面刚刚加载完成时,newVal==oldVal==undefined 的情况
                if(newVal==oldVal){
                    return;
                }
                $scope.num++;
            })
        }]);
    </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

  当页面加载完成时,$watch函数将会首次执行,这时的newValoldVal都为undefined

5. 解决ng-ifng-model值无效的问题

  ng-ifng-show的区别在于,前者将会移除DOM元素,而后者只是将元素的display设为none
  与其他指令一样,ng-if指令也会创建一个自己作用域,因此,如果在ng-if中添加了元素,并向元素属性增加ng-model指令,那么ng-model指令对应的作用域属于子级作用域,并非控制器注入的$scope作用域对象。

    <div ng-controller='myController'>
        <div>
            a的值:{{a}} <br>
            b的值:{{b}} <br>
        </div>
        <div>
            普通方式: <input type="checkbox" ng-model='a' />
        </div>
        <div ng-if='!a'>
            ngIf方式: <input type="checkbox" ng-model='$parent.b' />
        </div>
    </div>
    <script type="text/javascript">
        var app=angular.module('myapp',[]);
        app.controller('myController',['$scope',function($scope){
            $scope.a=false;
            $scope.b=false;
        }]);
    </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多