AngularJS - 从父控制器运行子控制器的功能

Posted

技术标签:

【中文标题】AngularJS - 从父控制器运行子控制器的功能【英文标题】:AngularJS - Run function of child controller from parent controller 【发布时间】:2019-04-01 16:03:00 【问题描述】:

我已经阅读了很多关于此的问题,但仍然找不到足够干净和可重复使用的解决方案。

我尝试过但不想使用的:

事件 - $emit 和 $broadcast, DOM 操作 - 例如 angular.element('nameOfElement').scope() 访问子范围, 子组件中的$onChange

简单示例

我已经构建了简化的场景来呈现问题。

在页面上有 TimerComponent 显示分钟和秒。它有控制器TimerController 来改变它的状态:start()stop()。在示例中有两个,都呈现不同的值。

计时器模板不包含用于操作它的按钮 - 这是有意的。我想从其他控制器启动和停止计时器。

孩子与父母的交流。我可以传递value 和函数回调onTick(),它们将每秒运行一次。

亲子交流: 如何从父组件运行 start() 或 stop() 函数?

timer.component.js

(function() 
    'use strict';

    TimerController.$inject = ['$interval']
    function TimerController($interval) 
        var ctrl = this;

        var interval = undefined;

        ctrl.start = start;
        ctrl.stop = stop;
        ctrl.minutes = minutes;
        ctrl.seconds = seconds;           

        function minutes() 
            return Math.floor(ctrl.value / 60);
        

        function seconds() 
            return (ctrl.value % 60);
        

        function start() 
            interval = $interval(function() 
                ctrl.value--;
                ctrl.onTick( 'value': ctrl.value );
            , 1000);
        

        function stop() 
            $interval.cancel(interval);
        
    

    angular.module('app').component('timer', 
        bindings: 
            value: '<',
            onTick: '&'
        ,

        templateUrl: 'timer.html',
        controller: TimerController
    );
)();

timer.html

<span ng-bind="$ctrl.minutes() + ':' + $ctrl.seconds()"></span>

app.html

<body ng-app="app" ng-controller="MainController as vm">
    <p>First timer: </p>
    <timer value="360" on-tick="vm.firstTimerTick(value)"></timer>

    <p>Second timer: </p>
    <timer value="120" on-tick="vm.secondTimerTick(value)"></timer>

    <p>
        <span ng-click="vm.startFirstTimer()">Start first timer</span>
    </p>
</body>

main.controller.js

(function() 
    'use strict';

    angular.module('app').controller('MainController', MainController);

    function MainController() 
        var ctrl = this;
        ctrl.firstTimerTick = firstTimerTick;
        ctrl.secondTimerTick = secondTimerTick;
        ctrl.startFirstTimer = startFirstTimer;

        function firstTimerTick(value) 
            console.log('FirstTimer: ' + value);
        

        function secondTimerTick(value) 
            console.log('SecondTimer: ' + value);
        

        function startFirstTimer() 
            /* How to run start() function of TimerController here? */
        

        function stopFirstTimer() 
            /* How to run start() function of TimerController here? */
        
    
)();

【问题讨论】:

【参考方案1】:

一种方法是使用新的ngRef directive:

<timer ng-ref="vm.timerOne" value="360" on-tick="vm.firstTimerTick(value)">
</timer>

然后在控制器中使用:

function startFirstTimer() 
    /* How to run start() function of TimerController here? */
    ctrl.timerOne.start();

ngRef directive 是作为 AngularJS V1.7.1 的新功能引入的。

有关详细信息,请参阅AngularJS ng-ref Directive API Reference。

【讨论】:

以上是关于AngularJS - 从父控制器运行子控制器的功能的主要内容,如果未能解决你的问题,请参考以下文章

从父控制器访问子模型

如何在 swift 中从父视图访问容器视图子视图

Swift - 将数据从父视图控制器传递到子视图控制器

从父级删除后保留的子视图控制器

应该从父 ViewController 还是子 ViewController 调用 popViewController?

组件不会从父angularjs接收更新