【AngularJS】—— 12 獨立作用域


前面通過視頻學習了解了指令的概念,這里學習一下指令中的作用域的相關內容。

通過獨立作用域的不同綁定,可以實現更具適應性的自定義標簽。借由不同的綁定規則綁定屬性,從而定義出符合更多應用場景的標簽。

本篇將會總結下面的內容:

  1 為何需要獨立作用域

  2 如何實現獨立作用域

  3 作用域的數據綁定

之前有一些錯誤,是由於replace拼寫錯誤導致的。

拼寫正確后,網友發現報錯,無法正常工作。這是因為模板中存在單標簽<br>,導致模板無法正確解析~

再次感謝博友們提出的錯誤!

獨立作用域的作用

  為了便於理解,先看一下下面這個例子:

<!doctype html>
<html ng-app="myApp">
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
    </head>
    <body>

        <div ng-controller="MainController">
            <xingoo></xingoo>
            <xingoo></xingoo>
            <xingoo></xingoo>
        </div>

        <script type="text/javascript">
            var myAppModule = angular.module("myApp",[]);

            myAppModule
            .controller('MainController', function($scope){

            })
            .directive("xingoo",function(){
                return {
                    restrict:'AE',
                    template:'<div><input type="text" ng-model="username"/>{{username}}</div><br>'
                };
            });
        </script>
    </body>
</html>

  可以看到,在script中,創建了一個指令,該指令實現了一個自定義的標簽。

  標簽<xingoo></xingoo>的作用是 替換成 一個輸入框和一個數據顯示。

  這樣就會出現下面的效果:

  分析:

  當我們自己創建某個指令時,這個指令肯定不可能只使用一次,是要重復多次使用的,有的在一個頁面內或者一個控制器內需要使用多次。

  類似上面的這種場景,在任何一個輸入框內改變數據,都會導致其他的標簽內的數據一同發生改變,這顯然不是我們想要的。

  這個時候就需要獨立作用域了。

 

如何實現獨立作用域

  下面看看獨立作用域的效果:

<!doctype html>
<html ng-app="myApp">
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
    </head>
    <body>

        <div ng-controller="MainController">
            <xingoo></xingoo>
            <xingoo></xingoo>
            <xingoo></xingoo>
        </div>

        <script type="text/javascript">
            var myAppModule = angular.module("myApp",[]);

            myAppModule
            .controller('MainController', function($scope){

            })
            .directive("xingoo",function(){
                return {
                    restrict:'AE',
                    scope:{},//scope=true,
                    template:'<div><input type="text" ng-model="username"/>{{username}}</div><br>'
                };
            });
        </script>
    </body>
</html>

  只需要在定義指令時,添加scope:{}這個屬性,就可以使標簽擁有自己的作用域。

  僅僅是添加這一行代碼而已,就實現了獨立作用域。

  在進行輸入時,每個模板內使用自己的數據,不會相互干擾。

 

作用域數據綁定  

  自定義標簽或者進行擴展時,會有這樣的需求場景,要在標簽中添加一些屬性,實現一些復雜功能。

  關於這些屬性,獨立作用域是如何的做的呢?看看下面的內容吧。

  舉個例子:

<xingoo say="name"></xingoo>
<xingoo say="name()"></xingoo>

  假設傳入的是上面這種,我們如何區分它傳入的到底是變量呢?還是字符串呢?還是方法呢?

  因此AngularJS有了三種自定義的作用域綁定方式:

  1 基於字符串的綁定:使用@操作符,雙引號內的內容當做字符串進行綁定。

  2 基於變量的綁定:使用=操作符,綁定的內容是個變量。

  3 基於方法的綁定:使用&操作符,綁定的內容時個方法。

基於字符串的綁定@:

<!doctype html>
<html ng-app="myApp">
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
    </head>
    <body>

        <div ng-controller="MainController">
            <xingoo say="test string"></xingoo>
            <xingoo say="{{str2}}"></xingoo>
            <xingoo say="test()"></xingoo>
        </div>

        <script type="text/javascript">
            var myAppModule = angular.module("myApp",[]);

            myAppModule
            .controller('MainController', function($scope){
                $scope.str1 = "hello";
                $scope.str2 = "world";
                $scope.str3 = "angular";
            })
            .directive("xingoo",function(){
                return {
                    scope:{
                        say:'@'
                    },
                    restrict:'AE',
                    template:"<div>{{say}}</div>",
                    replace:true
                };
            });
        </script>
    </body>
</html>

  看一下代碼,在body中使用了三次自定義的標簽,每種標簽的內部有一個say的屬性,這個屬性綁定了一個雙引號的字符串。

  在指令的定義中,添加了scope:{say:'@'}這個鍵值對屬性,也就是說,angular會識別say所綁定的東西是一個字符串

  在模板中,使用表達式{{say}}輸出say所表示的內容。

  可以看到,雙引號內的內容都被當做了字符串。當然{{str2}}表達式會被解析成對應的內容,再當做字符串。

 

基於變量的綁定=:

<!doctype html>
<html ng-app="myApp">
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
    </head>
    <body>

        <div ng-controller="myAppCtrl">
            ctrl:<input type="text" ng-model="testname"><br>
            directive:<xingoo name="testname"></xingoo>
        </div>

        <script type="text/javascript">
            var myAppModule = angular.module("myApp",[]);

            myAppModule.controller("myAppCtrl",['$scope',function($scope){
                $scope.testname="my name is xingoo";
            }]);

            myAppModule.directive("xingoo",function(){
                return {
                    restrict:'AE',
                    scope:{ name:'=' },
                    template:'<input type="text" ng-model="name">',
                    repalce:true
                }
            })
        </script>
    </body>
</html>

  在上面的代碼中,可以看到

  1 在控制器myAppCtrl對應的div中,定義了一個變量ng-model —— testname。

  2 testname對應的是輸入框中輸入的值。

  3 然后把這個變量當做一個參數傳遞給xingoo這個標簽的name屬性。

  4 在xingoo標簽中,又把這個name綁定到模板中的一個輸入框內。

  最終兩個輸入框的內容被連接起來,無論改變哪一個輸入框內的值,testname與name都會發生改變。

  通過下面這張圖可以看出來:

  在指令中通過scope指定say綁定規則是變量的綁定方式。

  最終通過xingoo標簽內的屬性依賴關系把 testname與name連接在一起:

  

基於方法的綁定&:

  上面展示了基於字符串和變量的綁定方法,下面看看基於方法的綁定:

<!doctype html>
<html ng-app="myApp">
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
    </head>
    <body>

        <div ng-controller="myAppCtrl">
            <xingoo say="sayHello(name)"></xingoo>
            <xingoo say="sayNo(name)"></xingoo>
            <xingoo say="sayYes(name)"></xingoo>
        </div>

        <script type="text/javascript">
            var myAppModule = angular.module("myApp",[]);

            myAppModule.controller("myAppCtrl",['$scope',function($scope){
                $scope.sayHello = function(name){
                    console.log("hello !"+ name);
                };
                $scope.sayNo = function(name){
                    console.log("no !"+ name);
                };
                $scope.sayYes = function(name){
                    console.log("yes !"+ name);
                };
            }]);

            myAppModule.directive("xingoo",function(){
                return {
                    restrict:'AE',
                    scope:{
                        say:'&'
                    },
                    template:'<input type="text" ng-model="username"/><br>'+
                        '<button ng-click="say({name:username})">click</button><br>',
                    repalce:true
                }
            })
        </script>
    </body>
</html>

  這段代碼中scope中的綁定規則變成了&,也就是方法綁定。

  在body中,通過自定義標簽傳入了三個方法,分別是sayHello(name),sayNo(name),sayYes(name),這三個方法都需要一個name變量。

  在指令的定義中,模板替換成一個輸入框,一個按鈕:

  輸入框:用於輸入username,也就是三個方法需要的參數name。

  按鈕:點擊觸發函數——通過綁定規則,綁定到相應的方法。

  

  也就是說

  通過say在scope中的定義,angular知道了say對應的是個方法;

  通過{name:username}的關聯,知道了傳入的是username。

  從而交給對應的方法執行。

  

  頁面效果:

 

  參考

  [1] 大漠窮求,AngularJS實戰:http://www.imooc.com/video/3085/0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM