28

angular Docs に記載されているように、AngularJS には DOM ベースのコントローラー継承があります。

<div ng-controller="BaseController">
    <p>Base Controller Value: {{value}}</p>
    <button ng-click="updateValue()">Update In Base</button>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{value}}</p>
        <button ng-click="updateValue()">Update In Derived</button>
    </div>
</div>

スコープ変数「値」は BaseController にのみ存在します。これに基づいて、BaseController または DerivedController のメソッドで値を変更しながら、両方の値を更新する必要があるとします。ただし、個々のスコープ変数のみが更新されます。

これは同じ例を示すフィドルです: http://jsfiddle.net/6df6S/1/

現在のスコープの直接の子と直接の親に伝達するために、レベルでどのように変更を行うことができますか。

これを実装するには、

$scope.$watch

それまたはそのようなウォッチャーを使用せずにこれを行う方法はありますか?

編集1:

ここで $scope.$watch を使用することで、私が意味したことです

$scope.$watch("value", function () {
   $scope.$broadcast("childChangeListener"); //Downwards to all children scopes
   $scope.$emit("parentChangeListener"); //Upwards to all parent scopes
});

そのようなメカニズムを使用せずに、すべてのスコープで値が更新される方法を探していました。

4

6 に答える 6

50

複数のコントローラーが同じデータにアクセスする必要がある場合は、サービスを使用する必要があります。HTML の記述方法が制限されるため、スコープの継承に依存しないでください。たとえば、将来、DerivedController を BaseController の子にするべきではないと判断したとします。

通常、サービスはパブリック API を提供し、実装を非表示にする必要があります。これにより、内部のリファクタリングが容易になります。

HTML:

<div ng-controller="BaseController">
    <p>Base Controller Value: {{model.getValue()}}</p>
    <button ng-click="model.updateValue('Value updated from Base')">Update In Base</button>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{model.getValue()}}</p>
        <button ng-click="model.updateValue('Value updated from Derived')">Update In Derived</button>
    </div>
</div>

JavaScript:

app.factory('sharedModel', function () {
    // private stuff
    var model = {
        value: "initial Value"
    };
    // public API
    return {
        getValue:    function() { 
           return model.value; 
        },
        updateValue: function(value) {
           model.value = value;
        }
    };
});

function BaseController($scope, sharedModel) {
    $scope.model = sharedModel;
}

function DerivedController($scope, sharedModel) {
    $scope.model = sharedModel;
}

フィドル

また、コントローラー間の共有に $rootScope を使用することはお勧めしません。

于 2013-03-13T15:57:27.163 に答える
8

フィドルのバインディングは、スコープ内のプロパティに直接あります。必要な継承は、スコープ内のオブジェクトにデータバインディングを設定することで実現できます。

http://jsfiddle.net/2Dtyq/

scope.shared = {}    
scope.shared.value = "Something"

ただの代わりに

scope.value= "Something"

何が起こっている?
DerivedControllerが構築されている間、渡されるスコープは通常、BaseControllerのスコープから継承されます。
DerivedControllerのスコープオブジェクトには、「value」と呼ばれる独自のプロパティがまだありません。したがって、親のスコープから取得したプロパティにバインドされます。
これで、[ベースで更新]ボタンをクリックすると、両方のバインディングに反映されます。[派生で更新]ボタンをクリックすると、DerviedControllerのスコープに「value」という名前の新しいプロパティが作成されます。したがって、親のvalueプロパティへのバインドは壊れています。Update In Baseをクリックしても、2番目のデータバインディングは更新されません。
別のオブジェクトに配置すると、新しいプロパティが作成されないため、継承が維持されます。

于 2013-03-13T17:51:33.830 に答える
5

子コントローラーの文字列値を直接参照することはできません。プロトタイプの継承によりvalue、子スコープ (子コントローラーを使用すると作成される) でプロパティを設定すると、親スコープのプロパティを更新するのではなく、子スコープでそのプロパティが作成されます。

スコープはモデルではないため$scope、多くのプロパティで変数を汚染することは避ける必要があります。モデル オブジェクトを作成し、その上にサブ プロパティを作成します。このオブジェクトは、子コントローラー\スコープに沿って渡すことができます。

上記の点を説明するためにjsfiddleを変更しました。

また、プロトタイプ継承の煩わしさを理解するために、このwiki ページに目を通すことを強くお勧めします。

于 2013-03-13T14:08:08.450 に答える
2

$broadcastメソッドを見てください。ドキュメントの引用:

登録された ng.$ro​​otScope.Scope#$on リスナーに通知するすべての子スコープ (およびその子スコープ) にイベント名を下方にディスパッチします。

于 2013-03-13T13:06:03.387 に答える
0

これは、ngController が新しい $scope を作成し、値の参照が同じでないために発生します。$parent次のようなプロパティを使用して解決できます。

<div ng-controller="BaseController">
    <p>Base Controller Value: {{value}}</p>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{$parent.value}}</p>
    </div>
</div>

DerivedController では、次のようなものを使用できます。$scope.$parent.value

しかし、それを実装する最良の方法は、controllerAs構文を使用することです。

<div ng-controller="BaseController as BaseController ">
<p>Base Controller Value: {{BaseController.value}}</p>
<div ng-controller="DerivedController">
    <p>Derived Controller Value: {{BaseController.value}}</p>
</div>

DerivedController では、次のようなものを使用できます。$scope.BaseController.value

参照しているコントローラーが何であるかを知っているため、コードの可読性が向上します。詳細については、ngController DocsまたはDigging into Angular's “Controller as” syntax by ToddMotto を参照してください。

于 2015-01-26T17:41:14.740 に答える