transclude AngularJS でディレクティブを作成する場合、新しいスコープ、新しい子スコープ、または新しい分離スコープが必要ないかどうかを判断するにはどうすればよいですか。




component angular js (4)

私は、新しいディレクティブを書くときに使用するスコープのタイプを決定するのに役立ついくつかのガイドラインを探しています。 理想的には、フローチャートのようなものがあります。私は多くの疑問を抱き、正しい答え、新しい新しいスコープ、新しい子のスコープ、新しいスコープを飛ばしてしまうのですが、それはあまりにも多くのことを求めています。 私の現在の手っ取り早いガイドラインがあります:

ある要素の分離スコープを持つディレクティブを使用すると、同じ要素の他のディレクティブすべてが同じ(1つの)分離スコープを使用することになりますので、分離スコープを使用できるときにはこれが厳しく制限されません。

Angular-UIチーム(または多くのディレクティブを書いた人)が経験を共有できることを期待しています。

単に「再利用可能なコンポーネントに隔離されたスコープを使用する」という答えを加えないでください。


どのような大きな質問です! 私は他の人が何を言わなければならないか聞いてみたいが、ここで私が使用するガイドラインがある。

高高度の前提条件:スコープは、親コントローラ、ディレクティブ、およびディレクティブテンプレート間の通信に使用する「グルー」として使用されます。

親スコープ: scope: false 、新しいスコープはまったくありません

私はこれを非常に頻繁には使用しませんが、@MarkRajcokはディレクティブがスコープ変数にアクセスしていなければ(明らかに何も設定していません!)、これは私が心配している限りうまくいきます。 これは親ディレクティブのコンテキストでのみ使用される子ディレクティブ(ただしこれには常に例外があります)とテンプレートを持たない子ディレクティブにも役立ちます。 基本的に、テンプレートを持つものはスコープの共有には属しません。なぜなら、アクセスと操作のためにそのスコープを本質的に公開しているからです(ただし、このルールには例外があります)。

例として、私は最近、私が書いているSVGライブラリを使って(静的な)ベクトルグラフィックを描くディレクティブを作成しました。 $observe 2つの属性( widthheight )を$observeし、それらの計算を使用しますが、スコープ変数の設定も読み取りもテンプレートのないものです。 これは別のスコープを作成しない場合の良いユースケースです。 私たちは1つを必要としないので、なぜ迷惑?

しかし、別のSVGディレクティブでは、使用する一連のデータが必要でしたが、さらに小さな状態のビットを格納する必要がありました。 この場合、親スコープを使用することは無責任です(一般的に言えば)。 だから代わりに...

子スコープ: scope: true

子スコープのディレクティブはコンテキストを意識しており、現在のスコープと対話することを意図しています。

明らかに、分離された範囲を超えるこの主な利点は、ユーザーが任意の属性で補間を自由に使用できることです。 分離されたスコープのディレクティブでclass="item-type-{{item.type}}"を使用すると、デフォルトでは機能しませんが、補間されたものはデフォルトでは親スコープ また、指令自体は、親の汚染や損傷を心配することなく、属性や表現を独自の範囲で安全に評価することができます。

たとえば、ツールチップは単に追加されるものです。 他のディレクティブや補間された属性をここで使用する予定であるため、分離スコープは機能しません(デフォルトでは、以下を参照)。 ツールチップは機能強化に過ぎません。 しかし、ツールチップでは、サブディレクティブやテンプレートで使用するスコープをいくつか設定し、独自の状態を管理する必要があるため、親スコープを使用するのは非常に難しいでしょう。 私たちはそれを汚染しているか、それを傷つけています。どちらもbuenoではありません。

私は自分自身がスコープを分離または親よりも頻繁に子スコープを使用していることがわかります。

分離スコープ: scope: {}

これは再利用可能なコンポーネント用です。 :-)

しかし真剣に、私は「再利用可能なコンポーネント」を「自己完結型のコンポーネント」と考えています。 その目的は、特定の目的に使用されるため、他のディレクティブと組み合わせたり、DOMノードに他の補間された属性を追加することは本質的に意味がありません。

具体的には、このスタンドアロン機能に必要なものは、親スコープのコンテキストで評価された指定された属性によって提供されます。 一方向文字列( '@')、一方向式( '&')、双方向変数バインディング( '=')のいずれかです。

自己完結型コンポーネントでは、他のディレクティブや属性を単独で存在させるため、それを適用する必要はありません。 そのスタイルは独自のテンプレート(必要な場合)によって管理され、必要に応じて適切なコンテンツを継承することができます。 スタンドアロンなので、私たちはそれを別のスコープに入れて、「これを混乱させないでください。これらの属性を使って定義済みのAPIを提供しています。」

適切なベストプラクティスは、ディレクティブリンクとコントローラ関数からできるだけ多くのテンプレートベースのものを除外することです。 これは別の「APIのような」設定ポイントを提供します。ディレクティブのユーザーは単にテンプレートを置き換えることができます! 機能はすべて同じままであり、内部APIは決して触れられませんでしたが、必要なだけスタイリングとDOM実装を混乱させる可能性があります。 ui / bootstrapは、Peter&Pawelがすばらしいので、これをうまく実行する方法の素晴らしい例です。

分離スコープは、除外に使用するのにも最適です。 タブを押す。 それらは機能全体だけでなく、 内部にあるものは、親スコープ内から自由に評価することができ、タブ(およびペイン)には何でもしても構いません。 タブは明らかに(テンプレートと対話するために)スコープに属する独自の状態を持っていますが、その状態は使用されたコンテキストとは無関係です。タブの指示をタブの指示にするためのものです。 さらに、タブで他のディレクティブを使用することはあまり意味がありません。 タブになっています。すでにその機能を持っています。

より多くの機能でそれを囲むか、より多くの機能を継承しますが、その指示はすでにそれが何であるかです。

@ProLoserが彼の答えで示唆したように、分離されたスコープのいくつかの制限(すなわち機能)の周りには方法があることに注意する必要があります。 例えば、子スコープのセクションでは、隔離スコープ(デフォルト)を使用するときに、非ディレクティブ属性の補間についての補間について述べました。 しかし、ユーザーは、たとえば単にclass="item-type-{{$parent.item.type}}"を使用することができ、もう一度動作します。 したがって、子スコープに対して隔離スコープを使用する魅力的な理由があるにもかかわらず、これらの制限のいくつかが心配な場合は、必要に応じてほぼすべてを回避することができます。

概要

新しいスコープのないディレクティブは読み取り専用です。 彼らは完全に信頼されて(すなわち、アプリの内部に)、彼らはジャックに触れていない。 子スコープのディレクティブは機能を追加しますが、唯一の機能ではありません。 最後に、分離スコープは、目標全体であるディレクティブに対するものです。 彼らはスタンドアロンなので、彼らが悪口になるのは大丈夫です(そしてほとんどの "正しい")。

私は最初の考えを出したいと思っていましたが、もっと多くのことを考えると、これを更新します。 しかし、聖なるくそ - これは、SOの答えのために長いです...

PS:完全に接線ですが、私たちはスコープについて話しているので、私は "プロトタイプ"と言いますが、他は "プロトタイプ"を好みます。これはより正確であるように見えますが、 :-)


私はウルムと同意する。 理論的には、孤立したスコープはすばらしい "ポータブルな"ものですが、私のアプリをビルドする際には、いくつかのディレクティブ(他のものの中に入れ子にしたり、属性を追加する)を組み込む必要がありました。ドメイン固有言語の目的である独自のHTML。

最後に、ディレクティブの各DOM呼び出しで複数の属性を持つチェーン全体のグローバル値または共有値を渡す必要があるのはあまりにも奇妙です(スコープを分離する必要があります)。 DOM内のすべてのものを繰り返し記述するのはちょうど馬鹿に見えますが、たとえそれらが共有オブジェクトであっても、効率が悪いと感じます。 また、指令宣言を不必要に複雑にします。 $ parentを使って "到達して"指示文のHTMLから値を取得する回避策は、Very Bad Formのようです。

私も、アプリケーションを変更して、ほとんどのアイソレートを持つ子スコープ・ディレクティブ(単純で非反復的な属性を渡すことができるもの以外に、親から何もアクセスする必要のないもののみ)を変更しました。

このようなことが起こる前に何十年もドメイン固有言語の夢を夢見てきたAngularJSは、このオプションを提供していることを歓迎しています。この分野で開発者が増えるにつれて、また、建築家が作成、展開、デバッグすることも容易です。

- D


多くのディレクティブを書いた後、私はそれほどisolatedれていないスコープを使うことに決めました。 データがカプセル化され、親スコープにデータが漏れないようにすることは魅力的ですが、一緒に使用できるディレクティブの量は厳しく制限されています。 そう、

あなたが書こうとしているディレクティブが完全に単独で動作し、それを他のディレクティブと共有しない場合は、 独立したスコープに進んでください。 (プラグインできるコンポーネントのように、エンド・デベロッパー向けのカスタマイズはそれほどありません)(ディレクティブを含むサブ要素を記述しようとすると非常に手間がかかります)

あなたが書くつもりのディレクティブが、スコープの内部状態や明示的なスコープの変更(ほとんど非常に単純なもの)を必要としないdom操作を行うだけの場合 新しい範囲には行きません 。 ( ngShowngMouseHoverngClickngRepeat

あなたが書くつもりのディレクティブが親スコープ内のいくつかの要素を変更する必要があるだけでなく、いくつかの内部状態を処理する必要がある場合は、 新しい子スコープに進んでください。 ( ngControllerなど)

ディレクティブのソースコードを確認してhttps://github.com/angular/angular.js/tree/master/src/ng/directivehttps://github.com/angular/angular.js/tree/master/src/ng/directive : https://github.com/angular/angular.js/tree/master/src/ng/directive
彼らのことを考える方法を大いに助けます


ちょうど私の現在の理解を追加し、それが他のJSコンセプトとどのように関係しているかを追加すると考えまし

デフォルト(宣言されていないか、スコープがfalseなど)

これは哲学的にはグローバル変数を使うことと同じです。 あなたのディレクティブは、親コントローラ内のすべてにアクセスできますが、それらにも影響を与え、同時に影響を受けています。

範囲:{}

これはモジュールのようなもので、使いたいものは明示的に渡す必要があります。 あなたが使用するEVERYディレクティブが独立したスコープである場合、EVERY JSファイルを作成して、すべての依存関係を注入する際にオーバーヘッドの大きい独自のモジュールを作成することと同等になります。

スコープ:子

これは、グローバル変数と明示的パススルーの中間に位置します。 これはjavascriptのプロトタイプチェーンに似ていて、親スコープのコピーを拡張するだけです。 分離スコープを作成し、親スコープのすべての属性と関数を渡すと、機能的にはこれと同等です。

重要な点は、ANYディレクティブはどのような方法でも記述できるということです。 さまざまなスコープ宣言は、整理に役立ちます。 すべてをモジュールにすることもできますし、すべてのグローバル変数を使用して、非常に注意することもできます。 メンテナンスを容易にするために、ロジックを論理的に一貫性のある部品にモジュール化することが望ましいです。開かれた草原と閉鎖された刑務所の間にはバランスがあります。 これが難しいのは、人々がこれについて学ぶとき、ディレクティブの仕組みを学んでいると思っていますが、実際にはコード/ロジック組織について学んでいると思います。

ディレクティブがどのように機能するかを理解するもう一つのことは、ngIncludeについて学習することです。 ngIncludeはHTMLパーシャルをインクルードするのに役立ちます。 最初にディレクティブを使用し始めたとき、テンプレートを使用してコードを減らすことができましたが、実際にはロジックを付加していませんでした。

もちろん、angleの指示とangular-uiチームの作業との間には、私がまだ何もしていない独自の指示を作成していないので、これに関する私の見解は完全に間違っているかもしれません。





angularjs-scope