zoukankan      html  css  js  c++  java
  • angularJS在创建指令需要注意的问题(指令中使用ngRepeat)

      现在发现,当初的自己真的是太菜了,为什么你在指令中更改数据,没有作用呢?这其实是原型链的问题。

      详细的我就不在这里说了,有位大神早已发布了这个内容,在这里复制个地址给大家,有兴趣的可以看看

      http://www.angularjs.cn/A09C

     ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

      忙活了一天终于写出了一个完整的angular指令,在后面的文章再来讲我制作的排序指令,由于还是菜鸟此文章仅仅用来借鉴,希望各位看到有不对的地方,希望能够指点一下。

      这里首先要讲的是angular在创建指令是经常会遇到的几个问题。

      1.作用域绑定策略

        这个其实不知道被讲了多少篇了,但是只有自己开始动手写才发现是很挺复杂的。这里只讲绑定策略,另外的scope:true和scope:false就跳过了

        第一个方法是“@”,这个的意思其实是绑定字符串,实际上是拿到该对象的值,并且是单向的 外部作用域可以影响内部作用域,但指令内部作用域却无法影响外部的作用域,在绑定的时候需要加上{{}} 代表引用scope作用域的值,没加上{{}}代表引用的是一个普通的字符串

        第二个方法是“=”,这个的意思是绑定对象,是双向的外部作用域可以影响内部作用域,但指令内部作用域也可以影响外部的作用域

         第三个方法是“&”,这个是用与controller和指令之间的交互的,控制器的方法可以绑定在这上面使用

        另外在html上如果出现用”-“的命名方法 则在js文件中需要”-“后面的第一个字母要大写,例如<hello-world></hello world> 则在js文件中需要用helloWorld命名

      2.在指令中使用ng内置指令

        这是非常常见的操作,但是类似ng-repeat,ng-switch等等指令是会创建自己的作用域的,这个时候你就需要注意作用域的问题了,这个作用域问题是挺致命的。

        下面写个例子给大家看看关于ng-repeat的问题

    这个是一个手风琴效果,内容是来自于《用angularJS开发下一代Web应用的》,没读过的朋友建议买来看一下,还是有很大帮助的,效果就像bootstrap的手风琴,但是我要讲一些书上没有说的东西,大家可以将代码复制下来执行看看。

    var myApp = angular.module('MyApp', []);
    myApp.controller('myCtrl', ['$scope', function($scope){
        $scope.isReverse = false;
        $scope.menuItems = [{
                                title : "This first",
                                content : "This first content"      
                            },{
                                title : "This second",
                                content : "This second content"      
                            },{
                                title : "This third",
                                content : "This third content"      
                            }];
    }]);
    myApp.directive('accroding',function(){
        return {
            controller: function($scope, $element, $attrs, $transclude) {
                var tabItems = [];
                this.getOpen = function(selectedItem){
                    angular.forEach(tabItems, function(value, key){
                        if(value != selectedItem){
                            value.isOpen = false;
                        }
                    });
                }
                this.addItem = function(tabItem){
                    tabItems.push(tabItem);
                }
    
            },
            restrict: 'EA', 
            template: '<div ng-transclude></div>',
            replace: true,
            transclude: true,        
            link: function($scope, iElm, iAttrs, controller) {
                
            }
        };
    });
    myApp.directive('expender', [function(){
        return {
            scope: {
                title : '=expenderTitle',
                isReverse : '=expenderIsreverse',
            }, 
            require: '^accroding', 
            restrict: 'EA', 
            template: '<div>'+
                      '<div ng-click="toggle()">{{title}} || isReverse:{{isReverse}}</div>'+
                      '<div ng-show="isOpen" ng-transclude></div>'+
                      '</div>',
            replace: true,
            transclude: true,
            link: function($scope, iElm, iAttrs, controller) {
                $scope.isOpen = false;
                controller.addItem($scope);
                $scope.toggle = function(){
                    $scope.isOpen = !$scope.isOpen;
                    controller.getOpen($scope);
                    $scope.isReverse = !$scope.isReverse;                
                }
            }
        };
    }]);
    <accroding>
            <expender ng-repeat="item in menuItems" expender-title="item.title" expender-isreverse="order.isReverse">
                {{item.content}}
            </expender>
        </accroding>
        <br>
        <div ng-repeat="item in menuItems">
            {{item.content}} | {{item.title}} || {{isReverse}} 
        </div>

      没错,你发现了什么,你明明有绑定策略‘=’去绑定,但是你点击div触发toogle()的时候,却发现外部的isReverse没有发生改变,指令内部的isReverse却发生改变了。也就是说你并没有双向绑定,这是什么问题呢?让我们看看修改之后的例子

    var myApp = angular.module('MyApp', []);
    myApp.controller('myCtrl', ['$scope', function($scope){
        $scope.order = {
            isReverse : "false",
            predicate : "2"
        };
        $scope.menuItems = [{
                                title : "This first",
                                content : "This first content"      
                            },{
                                title : "This second",
                                content : "This second content"      
                            },{
                                title : "This third",
                                content : "This third content"      
                            }];
    }]);
    myApp.directive('accroding',function(){
        return {
            controller: function($scope, $element, $attrs, $transclude) {
                var tabItems = [];
                this.getOpen = function(selectedItem){
                    angular.forEach(tabItems, function(value, key){
                        if(value != selectedItem){
                            value.isOpen = false;
                        }
                    });
                }
                this.addItem = function(tabItem){
                    tabItems.push(tabItem);
                }
    
            },
            restrict: 'EA',
            template: '<div ng-transclude></div>',
            replace: true,
            transclude: true,
            link: function($scope, iElm, iAttrs, controller) {
                
            }
        };
    });
    myApp.directive('expender', [function(){
        // Runs during compile
        return {
            scope: {
                title : '=expenderTitle',
                isReverse : '=expenderIsreverse',
                predicate : '=expenderPredicate',
            }, 
            require: '^accroding',
            restrict: 'EA', 
            template: '<div>'+
                      '<div ng-click="toggle()">{{title}} {{isReverse}} {{predicate}}</div>'+
                      '<div ng-show="isOpen" ng-transclude></div>'+
                      '</div>',
            replace: true,
            transclude: true,
            link: function($scope, iElm, iAttrs, controller) {
                $scope.isOpen = false;
                controller.addItem($scope);
                $scope.toggle = function(){
                    $scope.isOpen = !$scope.isOpen;
                    controller.getOpen($scope);
                    $scope.isReverse = !$scope.isReverse;
                    $scope.predicate = "22";
                }
            }
        };
    }]);
    <accroding>
            <expender ng-repeat="item in menuItems" expender-title="item.title" expender-isreverse="order.isReverse" expender-predicate="order.predicate">
                {{item.content}}
            </expender>
        </accroding>
        <div ng-repeat="item in menuItems">
            {{item.content}} | {{item.title}} || {{order.isReverse}} || {{order.predicate}}
        </div>

      把isReverse写成了对象的形式发现可以相互作用了,这就是ngRepeat的问题,ngRepeat创建了一个新的作用域,如果我们用基本数据类型去绑定的话,是无法成功的,需要将数据编程对象的形式去绑定,这样在指令内部改变值之后才可以与外部的作用域绑定,另外尽量在指令中不去使用ng-if,因为ng-if是根据节点决定添加和删除的节点的,当一个元素被ng-if从DOM中删除时,与其关联的作用域也会被销毁。而且当它重新加入DOM中时,则会生成一个新的作用域,而ng-show和ng-hide则不会。

  • 相关阅读:
    JSON排序
    iOS常用控件尺寸大集合
    Android 平台下Ftp 使用模拟器需要注意的问题
    PhoneGap Html5 App 横竖屏切换自动退出
    加减密 DES
    入学测试题
    黑马程序员——JAVA基础之反射
    黑马程序员——JAVA基础之网络编程
    黑马程序员——JAVA基础之正则表达式,网络爬虫
    黑马程序员——JAVA基础之GUI
  • 原文地址:https://www.cnblogs.com/HeJason/p/5258303.html
Copyright © 2011-2022 走看看