AngularJS中Scope間通訊Demo

Darren Ji發表於2016-01-22

 

在AngularJS中,每一個controller都有對應的Scope,而Scope間有時候需要通訊。比如有如下的一個controller巢狀:

 

<body ng-controller="AppCtrl">

    <table ng-controller = "ProductCtrl">
        ...
        <tr ng-repeat="product in products">
            <td>{{$index + 1}}</td>
            <td>{{product.name}}</td>
            <td>{{product.price | currency }}</td>
            <td><button ng-click="addToCart(product)">新增到購物車</button></td>
        </tr>
    </table>

    <div ng-controller="CartCtrl">
        ...
        <tr ng-repeat="product in cart">
            <td>{{$index+1}}</td>
            <td>{{product.name}}</td>
            <td>{{product.price  | currency}}</td>
            <td><button ng-click="removeFromCart(product)">remove</button></td>
        </tr>
    </div>
</body>

 

對應的controller部分大致是:

 

myApp.controller("AppCtrl", function($scope){
    $scope.title = "Product Manager";
})

myApp.controller("ProductCtrl", function($scope){
    $scope.products = [
        {name:"", price:50},
        ...
    ];
    
    $scope.addToCart = function(){
    
    }
});

myApp.controller("CartCtrl", function($scope){
    $scope.cart = [];
    $scope.removeFromCart = function(product){
    
    }
});

 

以上,呈現出的Scope間的關係如下:

$rootScope
.....$scope of AppCtrl
..........$scope of ProductCtrl
..........$scope of CartCtrl

問題來了,ProductCtrl中需要把product放到cart中,cart中需要獲取到product,兩者之間如何通訊呢


→ 當在ProductCtrl中執行addToCart動作時,讓$rootScope發一個廣播,通知所有的子Scope

 

myApp.controller("ProductCtrl", function($scope, $rootScope){
   $scope.products = [
        {name:"", price:50},
        ...
    ];
    
    $scope.addToCart = function(product){
        //讓$rootScope發一個廣播,所有子scope都知道了
        $rootScope.$broadcast("addProduct", product);
    }
})

 

可見,$rootScope通過$broadcast方法廣播事件,一個實參是事件名稱,一個實參是要傳遞的物件。

→ 在CartCtrl中需要偵聽來自$rootScope的事件,同時要把移除product的事件告知更高階別的Scope

 

myApp.controller("CartCtrl", function($scope){
    $scope.cart = [];
    
    //子scope要偵聽rootScope的事件
    $scope.$on("addProduct", add);
    
    function add(evt, product){
        $scope.cart.push(product);
    }
    
    $scope.removeFromCart = function(product){
        //子scope中的事件告知更高的scope
        $scope.$emit("removeProduct", product);
    }
})

 

可見,在子$scope中通過$on方法偵聽來自$rootScope的addProduct事件,並執行一個回撥函式;如果在子$Scope中執行一個事件要告知更高階別的Scope,這裡是removeFromCart事件,需要通過$emit方法,其中第一個實參也是事件名稱,第二個實參是傳遞物件。

→ 在AppCtrl中針對來自CartCtrl中的removeProduct事件

 

myApp.controller("AppCtrl", function($scope){
    $scope.$on("removeProduct", function(evt, data){
        console.log(data.name + "removed");
    })
})

 

可見,也是通過$on方法偵聽子$scope中emit發出的事件。

 

相關文章