如何在 AngularJS 中连接相邻的隔离示波器

How to Wire Up Adjacent Isolated Scopes in AngularJS

我还在学习 AngularJS,我有一个概念性的问题:在 AngularJS 中连接两个相邻的隔离作用域的最佳方法是什么?通过 'adjacent' 范围,我的意思是在同一层次上。考虑以下页面结构:

<div id="1" data-ng-app="angularApp">

    <div id="1A" data-ng-controller="colorCtrl as colorVm">
        <select data-ng-model="colorList" data-ng-options="color as color.name for color in colorVm.colors">
            <option>{{ color.name }}</option>
        </select>
    </div>

    <div id="1B" data-ng-controller="secondCtrl as secondVm">
        <light-color />
    </div>

    <div id="1C" data-ng-controller="thirdCtrl as thirdVm">
        <light-color />
    </div>

</div>

div#1B 和 div#1C 中的 'light-color' 指令需要能够从 div# 中的 select 菜单访问信息1A.在不将 'colorCtrl' 分配给 div#1 并扩大其范围的情况下执行此操作的最佳方法是什么?任何想法将不胜感激。

您可以将通用工厂注入每个控制器,作为在 3 个部分之间共享数据的一种方式。

function colorCtrl($scope, ..., colorFactory){
  // use colorFactory for modifying/storing color data
}

function secondCtrl($scope, ..., colorFactory){
  // use colorFactory for modifying/storing color data
}

function thirdCtrl($scope, ..., colorFactory){
  // use colorFactory for modifying/storing color data
}

你可以利用 scope events.

<div id="1A" data-ng-controller="colorCtrl as colorVm">
    <select ng-change="colorVm.colorChanged(selectedColor)" data-ng-model="selectedColor" data-ng-options="color as color.name for color in colorVm.colors">
        <option>{{ color.name }}</option>
    </select>
</div>

当用户从 select 菜单中选择颜色时 colorVm.colorChanged() 将使用模型值 selectedColor 调用。然后在 colorCtrl:

function ColorCtrl($scope, $rootScope) {
    this.colors = [...];
    this.colorChanged = function(selectedColor) {
       $rootScope.$broadcast('colorChanged', selectedColor);
    }
}

然后在 secondCtrl 你可以做:

function SecondCtrl($scope) {
    $scope.$on('colorChanged', function(event, color) {
        console.log(color + ' has been selected');
    });
}

你也可以在指令link函数中监听作用域事件:

...
link: function(scope) {
    scope.$on('colorChanged', function(event, color) {
        console.log(color + ' has been selected');
    });
}
...

在父作用域上初始化一个对象。让您的 ng-model 指令连接到该对象的 属性。该对象将由子作用域继承。

AngularJS 团队建议在控制器中进行初始化。在此示例中,我使用 ng-init 进行说明。在生产代码中,初始化最好在控制器中完成。

<div id="1" data-ng-app="angularApp">
    <div ng-init="x='{}'"></div>
    <div id="1A" data-ng-controller="colorCtrl as colorVm">
        <select ng-model="x.colorList" 
                ng-options="color as color.name for color in colorVm.colors">
        </select>
    </div>

    <div id="1B" data-ng-controller="secondCtrl as secondVm">
        <light-color color='x.colorList'/>
    </div>

    <div id="1C" data-ng-controller="thirdCtrl as thirdVm">
        <light-color color='x.colorList'/>
    </div>

</div>

在具有独立作用域的指令中,将属性设置为变量名,并使用双向绑定声明该属性。

angular.module('angularApp').directive('lightColor', function() {
    return {
        restrict: 'E',
        scope: {color: '='},
        template: '<p> lightColor color.name={{color.name}}</p>'
    }
})

记住,ng-model 的规则总是使用点。

DEMO on JSFiddle

我最终实现这一目标的方法是创建一个与所有三个控制器交互的服务。该文件现在看起来像这样:

<div id="1" data-ng-app="angularApp">

    <div id="1A" data-ng-controller="colorCtrl as colorVm">
        <select data-ng-model="colorVm.colorHelper.colorPick" data-ng-options="color as color.name for color in colorVm.colors">
            <option>{{ color.name }}</option>
        </select>
    </div>

    <div id="1B" data-ng-controller="secondCtrl as secondVm">
        <light-color light-color-choice="{{ secondVm.colorHelper.colorPick.name }}" />
    </div>

    <div id="1C" data-ng-controller="thirdCtrl as thirdVm">
        <light-color light-color-choice="{{ thirdVm.colorHelper.colorPick.name }}" />
    </div>

</div>

并且有一个服务 (colorHelper.service.js) 看起来像这样:

angular
    .module('angularApp')
    .service('colorHelper', function() {

        var self = this;

        self.colorPick;

    return self;
});

'colorHelper' 服务被输入到每个控制器的参数中。然后每个控制器都有一个新的 属性 设置为等于该控制器的 colorHelper 服务,即

var vm = this;
vm.colorHelper = colorHelper;

这样,每个控制器都可以通过其 colorHelper.colorPick.name 属性.

访问 colorVm.colorHelper.colorPick ng-model