22

たぶん私は頭がおかしいか、KnockoutJSに慣れすぎているのかもしれませんが、要素、コントローラー、または含まれる (ngInclude) パーシャルのスコープを定義するために、ドキュメントで ngWith ディレクティブを探し続けています。

例えば:

MyItem を次のように拡張するコントローラーを作成したいと思います。

MyModule.controller('MyItemCtrl', function($scope) {
    $scope.doSomethingToItem = function() {
        $scope.name = "bar";
    };
});

または、次のような MyItem のビュー/テンプレート:

<div ng-controller="MyItemCtrl">
    {{name}}
    <button ng-click="doSomethingWithItem()">Do Something</button>
</div>

しかし、これらのケースの両方で、 $scope がプロトタイプとしてモデルから継承されると想像していますMyItem

しかし、スコープはモデルから継承されません!!

それは私を困惑させます。

代わりに、私のモデルはスコープのプロパティです。

リピーターの場合:

<div ng-repeat="item in list">
    <div ng-controller="MyItemCtrl">
        {{item.name}}
        <button ng-click="doSomethingWithItem()">Do Something</button>
    </div>
</div>

これは、 andの代わりにitem.thisorを使用する必要があるすべての場所を意味します。どの関数がモデルにネイティブで、どれがコントローラーによってスコープに直接適用されたかを覚えておく必要があります。item.thatthisthat

部分的な表示名が必要な場合 (ばかげた例ですが、わかります) :

<h3>{{name}}</h3>

私はそれを書かなければなりません

<h3>{{item.name}}</h3>

モデルが常にitem であることを確認します。item通常は、プロパティでスコープを定義するためにディレクティブでラップするだけです。

私がやりたいと感じることが多いのは、単純に次のことです。

<div ng-include="'my/partial.html'" ng-with="item"></div>

また

<div ng-repeat="list" ng-controller="MyItemCtrl">            
    {{name}}
    <button ng-click="doSomethingWithItem()">Do Something</button>
</div>

私が見つけていない魔法の指示はありますか?それとも、私は完全に間違っていて、トラブルを探しているだけですか?

ありがとう。

編集:

スコープをモデルとして使用することの危険性を説明してくれた Brandon Tilley に感謝します。しかし、私はまだ、宣言的なスコープ操作を迅速に行う必要があることに気づき、ng-with ディレクティブを望んでいます。

たとえば、アイテムのリストがあり、クリックすると、選択したアイテムの展開ビューが表示されるとします。あなたはそれを次のように書くかもしれません:

<ul>
    <li ng-repeat="item in items" ng-click="selection = item">{{item.minView}}</li>
</ul>
<div ng-controller="ItemController">
    {{selection.maxView}}
</div>

selection.propertyここで、私が望むものではなく、選択した項目のプロパティを取得する必要があります: item.property。私も使用する必要がありselectionますItemController! このビューと完全に結合するようにします。

この単純な例では、ラッピング コントローラーを使用して動作させることができますが、要点を示しています。

私は非常に基本的なwithディレクティブを書きました:

myApp.directive('with', ['$parse', '$log', function(parse, log) {

    return {
        scope: true,
        link: function(scope, el, attr) {
            var expression = attr.with;
            var parts = expression.split(' as ');

            if(parts.length != 2) {
                log.error("`with` directive expects expression in the form `String as String`");
                return;
            }

            scope.$watch(parts[0], function(value) {
                scope[parts[1]] = value;
            }, true);
        }
    }

}]);

ある式を別の値に解析する新しいスコープを作成するだけで、次のことが可能になります。

<ul>
    <li ng-repeat="item in items" ng-click="selection = item">{{item.minView}}</li>
</ul>
<div with="selection as item" ng-controller="ItemController">
    {{item.maxView}}
</div>

これは私にとって無限に役立つようです。

ここで何か不足していますか?どういうわけか自分自身を困らせているだけですか?

4

4 に答える 4

21

ng-repeat のソースの周りに配列を配置するだけで、機能的に ng-with になることがわかりました。:)

<div ng-repeat="name in [vm.dto.Person.Name]" >
  <input type="text" ng-model="name.First" />
  <input type="text" ng-model="name.Last" />
</div> 

一部の純粋な人はこれが気に入らないようです...また、良い代替手段があるようには見えません.

于 2014-07-18T07:33:17.717 に答える
10

これは素晴らしい質問です。これが別のフロントエンドフレームワークから来て混乱する可能性があることはわかりますが、Angular では、スコープにはモデルへの参照があり、記述している構文は正常です。個人的には、スコープをビュー モデルのようなものとして説明するのが好きです。

AngularJS の作成者である Miško Hevery は、約 30 分から始まり、約 3 分間続くこのビデオでこの概念をうまく説明しています。

スコープはモデルだと思われることがよくありますが、そうではありません。Scopeにはモデルへの参照があります。[...]ビューでは、model dotアクセスしたいプロパティを指定します。

ngWith探していることを実行するディレクティブを作成することは可能かもしれませんが、Angular はスコープにプロトタイプの継承を使用するため、前述のビデオの 31:10で Miško が説明しているのと同じ問題に遭遇する可能性があります(親スコープの値を更新していると思いますが、実際にはそうではありません)。AngularJS のプロトタイプ継承の詳細については、AngularJS wikiの The Nuances of Scope Prototypal Inheritanceという優れた記事をご覧ください。

于 2013-04-20T20:37:13.273 に答える
0

ノックアウトから来るときのこれの1つの副作用は、より少ない責任でより多くのコンポーネントを作成することを奨励することであり、もちろんコンポーネント内では「これ」はそのコンポーネントのビューモデルです。本当に面倒なところまで来たら、新しいコンポーネントが必要な兆候かもしれません。

そして、自分がいるスコープについて考えずに、コンポーネント ビュー モデル内の何かを参照できるのは確かに素晴らしいこと$parents[2]です$root

PS。はい、ノックアウトで使用できることはわかっています。letつまり、少ない$ものです。

私は Angular のことをやっているときに間違いなくノックアウトを見逃しています (私はまだ両方を使用していますtitle="Customer #{{ row.customerId }} - {{ row.fullName }}") data-bind

于 2018-01-08T01:52:11.067 に答える