2016-11-22 7 views
0

controller as構文を使用するように私のコードを隠そうとしていました。なぜ 'controller as'は子コントローラから親スコープのプロパティに直接アクセスできないのですか?

// <div ng-controller="ParentCtrl"> 
// <div ng-controller="ChildCtrl"></div> 
// </div> 
// 
app.controller('ParentCtrl', function ($scope) { 
    $scope.x.title = 'Some title'; 
}); 


app.controller('ChildCtrl', function ($scope) { 
    console.log($scope.x.title); 
}); 

しかしcontroller asと:しかし、私は1つが、もはや直接、親コントローラの変数を使用することはできませんcontroller as構文を使用して、私は何を意味する($スコープ付き)古い方法で、私はこれを行うことができ、あることに驚きました、私はこの(このquestionのおかげで)しなければならない。なぜなら1)

// <div ng-controller="ParentCtrl as pc"> 
// <div ng-controller="ChildCtrl as cc"></div> 
// </div> 
// 
app.controller('ParentCtrl', function() { 
    this.x.title = 'Some title'; 
}); 


app.controller('ChildCtrl', function ($scope) { 
    console.log($scope.pc.x.title); 
}); 

これは非常に迷惑です。 htmlページで親コントローラの名前がpcであることを知っておく必要があります。 2)。私は一括検索を実行することはできません$scope => vm (or this)のため、プロパティが継承されている場合は動作しませんので、置き換えます。

誰でもcontroller asが導入されたときの背後にある根本的な理由を教えてください。

私はスコープ継承の多くを使用する場合私は右controller as避ける必要がありますか?または、スコープ継承は一般的に有害であると考えられているため、推奨できませんか?

答えて

3

いいえ、機械的な検索と置換はできません。現在、異なるスコープの値が混在しており、controller-as構文はそれらを区切るように設計されているためです。親スコープの一部がtitleを使用していて、子スコープでtitleを再度使用して親のスコープを非表示にした場合を避けることは、特にそうです。または、悪いことに、あなたが親のtitleを更新していると思ったときは、それを1つの子スコープで隠すだけでした。

したがって、アクセスする各値がどの親スコープに含まれているかを実際に調べる必要があります。つまり、スコープのモデルを参照するために使用された名前をスコープの継承ツリーから取り出す場合は、実際にその名前を知る必要があります。

より良い解決策は、ディレクティブを使用することです。または角度1.5以降のコンポーネントから行うことができます。子コントローラの代わりに、親値を取得するためにスコープをクロールすることで、目的の値をパラメータとしてディレクティブ/コンポーネントに渡します。次に、親がアクセスしたい値を公開する責任を負います。または、ディレクティブまたはコントローラのrequireプロパティを使用して、特定の親に埋め込まれ、親のコントローラが子のコントローラに直接バインドされる場合にのみ動作する子を作成できます。

ここにはangular documentationの例があります。しかし、私はあなたの最初の段落に同意

angular.module('docsTabsExample', []) 
.component('myTabs', { 
    transclude: true, 
    controller: function MyTabsController() { 
    var panes = this.panes = []; 
    this.select = function(pane) { 
     angular.forEach(panes, function(pane) { 
     pane.selected = false; 
     }); 
     pane.selected = true; 
    }; 
    this.addPane = function(pane) { 
     if (panes.length === 0) { 
     this.select(pane); 
     } 
     panes.push(pane); 
    }; 
    }, 
    templateUrl: 'my-tabs.html' 
}) 
.component('myPane', { 
    transclude: true, 
    require: { 
    tabsCtrl: '^myTabs' 
    }, 
    bindings: { 
    title: '@' 
    }, 
    controller: function() { 
    this.$onInit = function() { 
     this.tabsCtrl.addPane(this); 
     console.log(this); 
    }; 
    }, 
    templateUrl: 'my-pane.html' 
}); 
+0

:myPaneコントローラの内部で使用すると、this.tabsCtrlとして、親コントローラにアクセスすることができますし、重要なのは、それは名前が親コントローラのためではなく、親を使用するかを決定子であることに注意してください実際のコードでは、隠された親の問題を回避するドット構文の古いイディオムに従います。私はこれを反映するために私の質問を更新しました。私はあなたが良い解決策であると確信していますが、コンポーネントを使用するために私のアプリケーションを移行することはかなり大きな変化であり、私はコントローラーが低い垂木であると思っていました...(私は、探偵はDOMの変更によく使われます) – swang

+0

@swangはい、controllerAsは間違いなく最初のステップですが、あなたはまだ親を見つけるために範囲をクロールしなければならないということを受け入れる必要があります。このステップを完了すると、スコープのクロールを削除するコンポーネントがコンポーネントになります。適切な要約については、http://ngmigrate.telerik.com/from-ng-controller-to-component-classesを参照してください。 – Duncan

関連する問題