2013-09-26 50 views

回答

126

您可以使用$broadcast從父到子:

function ParentCntl($scope) { 

    $scope.msg = ""; 
    $scope.get = function(){ 
     $scope.$broadcast ('someEvent'); 
     return $scope.msg;   
    } 
} 

function ChildCntl($scope) {    
    $scope.$on('someEvent', function(e) { 
     $scope.$parent.msg = $scope.get();    
    }); 

    $scope.get = function(){ 
     return "LOL";  
    } 
} 

工作小提琴:http://jsfiddle.net/wUPdW/2/

UPDATE:還有一種版本,少加上和更可測試:

function ParentCntl($scope) { 
    $scope.msg = ""; 
    $scope.get = function(){ 
     $scope.$broadcast ('someEvent'); 
     return $scope.msg;   
    } 

    $scope.$on('pingBack', function(e,data) { 
     $scope.msg = data;   
    }); 
} 

function ChildCntl($scope) {    
    $scope.$on('someEvent', function(e) { 
     $scope.$emit("pingBack", $scope.get());   
    }); 

    $scope.get = function(){ 
     return "LOL";  
    } 
} 

小提琴:http://jsfiddle.net/uypo360u/

+0

非常酷!但是,如果你不想(想)知道調用者範圍在哪裏(我的意思是在'$ scope。$ parent'或'$ scope。$ parent。$ parent'等中)?啊,是的:通過params傳遞迴調! :) – user2173353

+0

@ user2173353你說得很對;還有一種方法:從孩子向父母發放'$ emit'。我認爲這是一個更新我的答案的時間。 – Cherniv

+0

在這種情況下,調用全局監聽器是什麼地方,子控制器是個好主意嗎?它不是反模式,以後很難測試?我們不應該使用注射還是使用? – calmbird

27

讓我提出另一種解決方案:

var app = angular.module("myNoteApp", []); 


app.controller("ParentCntl", function($scope) { 
    $scope.obj = {}; 
}); 

app.controller("ChildCntl", function($scope) { 
    $scope.obj.get = function() { 
      return "LOL";  
    }; 
}); 

更少的代碼,並使用原型繼承。

Plunk

+0

有人可以解釋一下,如果這種方法比上面提到的事件驅動方法更好,那麼在哪種情況下,爲什麼?如果您有多個lvl層次結構的子控制器會怎麼樣?如果obj.get是在子控制器內的子控制器內定義的,只要沒有控制器具有相同的函數名稱定義,這會工作嗎?先謝謝你。 – ZvKa

+0

有趣......感謝您的評論,最讓我感動的是我認爲js prototypical/angularjs作用域的繼承只應用於一個方向.... child - >父或子作用域 - >父作用域,而不是其他方式周圍....但我想我失去了一些東西@ _ @ – ZvKa

+1

讓我糾正我說的這是不完全正確的。你說的是正確的: 範圍繼承只適用於一個方向.... child - > parent。 這裏發生的實際情況是,如果您在子作用域中定義$ scope.get,則只會在子作用域(有時稱爲基本定義)上定義「get」。但是當你定義$ scope.obj.get時,子範圍將查找在父範圍上定義的obj,該範圍位於層次結構的上方。 – Canttouchit

9

註冊孩子的功能父當孩子被初始化。爲了使模板清晰,我使用了「as」符號。

模板

<div ng-controller="ParentCntl as p"> 
    <div ng-controller="ChildCntl as c" ng-init="p.init(c.get)"></div> 
</div> 

CONTROLLERS

... 
function ParentCntl() { 
    var p = this; 
    p.init = function(fnToRegister) { 
    p.childGet = fnToRegister; 
    }; 
// call p.childGet when you want 
} 

function ChildCntl() { 
    var c = this; 
    c.get = function() { 
    return "LOL";  
    }; 
} 

「但是」,你說, 「ng-initisn't supposed to be used this way!」。嗯,是的,但

  1. 該文件並沒有解釋原因,並
  2. 我不相信文檔的作者考慮了所有可能的使用情況吧。

我說這對它很好用。如果你想讓我失望,請評論和理由! :)

我喜歡這種方法,因爲它使組件更加模塊化。唯一綁定模板,並意味着

  • 孩子控制器不必知道任何有關其反對增加其功能(如@ canttouchit的答案)
  • 父控件可與具有get函數
  • 不需要廣播,這將在一個大的應用程序變得非常難看,除非你嚴格控制事件的命名空間
任何其他子控件使用

這種方法更密切地接近Tero's idea of modularising with directives(注那在他的modularis編輯示例,contestants從父項傳遞到模板中的「子」指令)。

事實上,另一種解決方案可能是考慮將ChildCntl作爲指令並使用&綁定來註冊init方法。

+1

我知道這是一箇舊的帖子,但這似乎是一個壞主意,因爲父母可以在孩子被銷燬後保留對孩子的引用。 –

相關問題