AngularJs(九)--指令(五)---自定义指令(二)

scope选项

<pre>
    <!DOCTYPE html>
    <html lang="en" ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            #div1 div{
                width: 200px;
                height:200px;
                border: 1px solid red;
                display: none;
            }
            #div1 input.active{
                background-color: red;
            }
        </style>
        <script src="js/angular.min.js"></script>
        <script type="text/javascript">
            var m1= angular.module("myApp",[]);
            m1.directive("myTab",function(){
                return{
                    restrict:"E",
                    replace:true,
                    templateUrl:'temp1.html'
                };
            });
            m1.controller('Aaa',['$scope',function($scope){
                $scope.name= 'hello';
            }]);
        </script>
    </head>
    <body ng-controller="Aaa">
        <my-tab></my-tab>
        <!--指令的最大特点是可以复用的-->
        <!--<my-tab></my-tab>-->
        <!--在此标签上重新初始化name变量的值,由"hello" 改为 "hi"-->
        <my-tab ng-init="name ='hi'"></my-tab>
    </body>
    </html>
</pre>

temp1.html

<pre>
    <div id="div1">
        <input type="button" value="1" class="active"/>
        <input type="button" value="2"/>
        <input type="button" value="3"/>
        <div style="display: block">{{name}}</div>
        <div>22222</div>
        <div>33333</div>
    </div>
</pre>

运行结果如下图:
<img src="1.png"/>

分析:
1. myTab标签指令中的表达式的值变成“hi”,其实说明这个变量的查找是从内向外的,和作用域的方式是一样的。
2. 所以先找到的name值是<my-tab ng-init="name ='hi'">这个标签上的name值,即“hi”;如果没找到,就继续往外找,找到body当中,从而找到“hello”。
所以第二个tab标签中显示的值是“hi”,这是正确的;但有问题的是:第一个tab标签中显示的值也变成“hi”,即第二个tab标签的name值修改会影响到第一个tab标签的值的显示。
即说明默认情况下,这两个tab标签是共享作用域的。
问题:自定义标签在不同环境下、不同页面或者不同标签结构中,这时候如果所有的数据都是共享的,除非实现的功能是一模一样的,要不然就很麻烦了,扩展性会非常大。
解决办法:angularJs为自定义指令提供了一个scope选项,可以解决上述提到的问题。

1.scope独立作用域

默认为false,将scope设置为true,代表当前标签指令具备独立作用域
每一个标签指令中的作用域都是独立的,不会互相影响。
修改myTab标签指令如下:

<pre>
    m1.directive("myTab",function(){
      return{
          restrict:"E",
          replace:true,
          scope:true,
          templateUrl:'temp1.html'
      };
   });
</pre>

运行结果如下图所示:
<code><img src="2.png"></code>


但是,即使有独立作用域,还是能继承父级的数据。父级数据还是会影响子级的数据。

2.scope隔离作用域

可以使本层作用域不会与外层作用域有任何的瓜葛,只在当前标签指令内部单独起作用。
书写方式:

 <pre>
    m1.directive("myTab",function(){
      return{
          restrict:"E",
          replace:true,
          scope:{},<!-- 将scope值设置为“{}”,即代表隔离作用域-->
          templateUrl:'temp1.html'
      };
   });
 </pre>

此时的运行结果如下图所示:
<img src="3.png">
原因分析:
controller中的name($scope.name= 'hello';)是属于外层作用域的变量,myTab标签上的name<my-tab ng-init="name ='hi'">,也是属于外层作用域的变量;
所示标签内部的表达式{{name}}被隔离了,不能找到外部作用域下的数据了。

那么问题又来了,如何在标签指令的模板中绑定数据呢?

controller选项

angularJS的自定义指令中提供了一个controller选项,用来为模板绑定数据。
书写方式与普通的controller的类似。
代码如下所示:

<pre>
    <!DOCTYPE html>
    <html lang="en" ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            #div1 div{
                width: 200px;
                height:200px;
                border: 1px solid red;
                display: none;
            }
            #div1 input.active{
                background-color: red;
            }
        </style>
        <script src="js/angular.min.js"></script>
        <script type="text/javascript">
            var m1= angular.module("myApp",[]);
            m1.directive("myTab",function(){
                return{
                    restrict:"E",
                    replace:true,
                    scope:{},
                    controller:["$scope",function($scope){
                        $scope.name="good";
                    }],
                    templateUrl:'temp1.html'
                };
            });
            m1.controller('Aaa',['$scope',function($scope){
                $scope.name= 'hello';
            }]);
        </script>
    </head>
    <body ng-controller="Aaa">
        <my-tab></my-tab>
        <my-tab ng-init="name ='hi'"></my-tab>
    </body>
    </html>
</pre>

运行结果如下图所示:
<img src="4.png">
可以发现,自定义指令中的controller定义的数据,对于同一个指令是共享的。
还有,一直存在的一个问题,同一个指令标签多次调用,模板中的<div id="div1">id会重复。
那么像这种有差异的数据如何体现呢?
angularJs也是通过scope来解决,准确的说是依据scope的绑定策略来解决。

scope的绑定策略

“@”

作用:指定到底是谁变成了参数,并且这个参数的值是普通的字符串。

<pre>
    m1.directive("myTab",function(){
      return{
          restrict:"E",
          replace:true,
          scope:{
            <!--完整写法是:myId:'@myId',但是如果变量名是相同的,可以省略;若不同,则不能 -->
            myId:'@'
          },
          templateUrl:'temp1.html'
      };
   });
   ......
   <body ng-controller="Aaa">
       <my-tab my-id="div1"></my-tab>
       <my-tab my-id="div2"></my-tab>
   </body>
 </pre>

temp1.html

 <pre>
    <div id="{{myId}}">
     <!-- <div id="div1"> -->
         <input type="button" value="1" class="active"/>
         <input type="button" value="2"/>
         <input type="button" value="3"/>
         <div style="display: block">{{name}}</div>
         <div>22222</div>
         <div>33333</div>
     </div>
 </pre>

运行结果如下图所示:
<img src="5.png">
从图中可以看出:两个指令标签生成的id就变成不同的了,绑定策略成功了。
若scope绑定的变量名不同时,代码如下:

<pre>
    m1.directive("myTab",function(){
      return{
          restrict:"E",
          replace:true,
          scope:{
            <!--完整写法是:myId:'@myId',但是如果变量名是相同的,可以省略;若不同,则不能 -->
            myId:'@aaa'
          },
          templateUrl:'temp1.html'
      };
   });
   ......
   <body ng-controller="Aaa">
       <my-tab aaa="div1"></my-tab>
       <my-tab aaa="div2"></my-tab>
   </body>
 </pre>

temp1.html

 <pre>
    <div id="{{myId}}">
     <!-- <div id="div1"> -->
         <input type="button" value="1" class="active"/>
         <input type="button" value="2"/>
         <input type="button" value="3"/>
         <div style="display: block">{{name}}</div>
         <div>22222</div>
         <div>33333</div>
     </div>
 </pre>

运行效果与上图相似。

“=”

作用:指定到底是谁变成了参数,并且这个参数的值是一个可解析的数据,即变量。

<pre>
        <!DOCTYPE html>
        <html lang="en" ng-app="myApp">
        <head>
            <meta charset="UTF-8">
            <title>Title</title>
            <style>
                #div1 div,
                #div2 div{
                    width: 200px;
                    height:200px;
                    border: 1px solid red;
                    display: none;
                }
                #div1 input.active,
                #div2 input.active{
                    background-color: red;
                }
            </style>
            <script src="js/angular.min.js"></script>
            <script type="text/javascript">
                var m1= angular.module("myApp",[]);
                m1.directive("myTab",function(){
                    return{
                        restrict:"E",
                        replace:true,
                        scope:{
                            myId:'@aaa',
                            myName:'='
                        },
                        controller:["$scope",function($scope){
                            $scope.name="good";
                        }],
                        templateUrl:'temp1.html'
                    };
                });
                m1.controller('Aaa',['$scope',function($scope){
                    $scope.name= 'hello';
                }]);
            </script>
        </head>
        <body ng-controller="Aaa">
            <my-tab aaa="div1" my-name="name"></my-tab>
            <my-tab aaa="div2" my-name="name"></my-tab>
        </body>
        </html>
    </pre>

temp1.html

 <pre>
    <div id="{{myId}}">
     <!-- <div id="div1"> -->
         <input type="button" value="1" class="active"/>
         <input type="button" value="2"/>
         <input type="button" value="3"/>
         <div style="display: block">{{myName}}</div>
         <div>22222</div>
         <div>33333</div>
     </div>
 </pre>

运行结果如下图所示:
<img src="6.png">
从图中可以看出,此时{{myName}}解析出来的是”Aaa”controller中定义的name值。

&

作用是:绑定父级函数的一种传递传递方式。

<pre>
    <!DOCTYPE html>
    <html lang="en" ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            #div1 div,
            #div2 div{
                width: 200px;
                height:200px;
                border: 1px solid red;
                display: none;
            }
            #div1 input.active,
            #div2 input.active{
                background-color: red;
            }
        </style>
        <script src="js/angular.min.js"></script>
        <script type="text/javascript">
            var m1= angular.module("myApp",[]);
            m1.directive("myTab",function(){
                return{
                    restrict:"E",
                    replace:true,
                    scope:{
                        myId:'@aaa',
                        myName:'=',
                        myFn:'&'
                    },
                    controller:["$scope",function($scope){
                        $scope.name="good";
                    }],
                    templateUrl:'temp1.html'
                };
            });
            m1.controller('Aaa',['$scope',function($scope){
                $scope.name= 'hello';
                $scope.show = function (num){
                    alert(num);
                }
            }]);
        </script>
    </head>
    <body ng-controller="Aaa">
        <!--此时`my-fn="show(num)"`中的值只是字符串,还没有传值-->
        <my-tab aaa="div1" my-name="name" my-fn="show(num)"></my-tab>
        <my-tab aaa="div2" my-name="name" my-fn="show(num)"></my-tab>
    </body>
    </html>
</pre>

temp1.html:

<pre>
    <div id="{{myId}}">
    <!--此时myFn被调用,才需要传实参-->
        <input type="button" value="1" class="active" ng-click="myFn({num:456})"/>
        <input type="button" value="2"/>
        <input type="button" value="3"/>
        <div style="display: block">{{myName}}</div>
        <div>22222</div>
        <div>33333</div>
    </div>
</pre>

运行结果如下:
<img src="7.png">

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值