使用controller作为语法调用控制器方法

时间:2016-07-05 09:11:34

标签: javascript angularjs

假设我有两个相同控制器的实例" ControllerA"在包装控制器内使用ng-controller as语法进行实例化:

<div ng-contrller="MainController">
    <div ng-controller="ControllerA as Ctrl1"></div>
    <div ng-controller="ControllerA as Ctrl2"></div>
</div>

现在我想要实现的是我可以在Ctrl1.controllerFunction()内调用类似MainController的内容。通常我会使用$broadcast$on来实现类似的行为,当没有相同控制器的两个实例时,所以我不能在这里使用它。我也不想在preventDefault的事件对象上使用$broadcast,因为它会变得太乱。

1 个答案:

答案 0 :(得分:1)

没有一种简单的方法可以满足您的要求。 Ctrl1的范围未定义MainController,它位于子范围内。 Ctrl1Ctrl2甚至不在彼此相同的范围内,因此没有必要使用不同名称的真正原因。您也可以ng-repeatng-if创建和销毁ControllerA个实例,因此生命周期可能比MainController更短。

处理此问题的更好方法是反转责任并使ControllerA实例在创建时注册MainController,并在销毁时取消注册。如果对MainController也使用controllerAs语法,那么子控制器很容易在MainController上调用方法。

<div ng-controller="MainController as Main">
    <div ng-controller="ControllerA as Ctrl1" ng-init="Ctrl1.init('Ctrl1')"></div>
    <div ng-controller="ControllerA as Ctrl2" ng-init="Ctrl2.init('Ctrl2')"></div>
</div>

function ControllerA($scope) {
    const vm = this;
    vm.init = function(name) {
        $scope.Main.register(name, vm);
        $scope.$on('$destroy', function() {
            $scope.Main.deregister(name);
        });
    }
}

然后在register中编写合适的deregisterMainController函数以跟踪子控制器。类似的东西:

function MainController() {
    const vm = this;
    const children = {};
    vm.register = function(name, vm) { children[name] = vm; }
    vm.deregister = function(name) { delete children[name]; }

   // ... and now you can do 
    if (children.Ctrl1) children.Ctrl1.controllerFunction();
}

您可以将init方法放在MainController中,但这样会因为您需要子范围而难以取消注册。