50

この方法で3つの子コンポーネントを含むコンポーネントを作成しています:

<header-component>
<side-component>
<main-component>

メインコンポーネントには、ヒーローのリストが含まれています。ヘッダー コンポーネントには、メイン コンポーネントのビューをリスト ビューまたはグリッド ビューに切り替えるための 2 つのボタンが含まれています。

私が今抱えている問題は、ヘッダー コンポーネントからメイン コンポーネントにデータを渡すことです。そのため、グリッド ボタンをクリックすると、メイン コンテンツのビューが、行ビューと同じようにグリッド ビューに変更されます。

angular 1.5 の子コンポーネント間でデータをどのように渡すことができますか?

4

3 に答える 3

87

コンポーネントアプローチ

Angular 2 コンポーネント アプローチに合わせて、入力/出力アプローチを使用することをお勧めします。そうすれば、コンポーネントは概念的に同一になるため (構文のみが異なる)、Angular 2 に簡単に移行できます。だからここにあなたがそれを行う方法があります。

したがって、基本的には、ヘッダーとメイン コンポーネントが状態の一部をヘッダーと共有して、変更できるようにする必要があります。機能させるために使用できるアプローチはいくつかありますが、最も簡単なのは、中間の親コントローラー プロパティを使用することです。viewしたがって、親コントローラー (またはコンポーネント)が、ヘッダー (読み取りおよび変更可能) とメイン (読み取り可能) コンポーネントの両方で使用するこのプロパティを定義していると仮定しましょう。

ヘッダー コンポーネント: 入力と出力。

単純なヘッダー コンポーネントは次のようになります。

.component('headerComponent', {
  template: `
    <h3>Header component</h3>
    <a ng-class="{'btn-primary': $ctrl.view === 'list'}" ng-click="$ctrl.setView('list')">List</a>
    <a ng-class="{'btn-primary': $ctrl.view === 'table'}" ng-click="$ctrl.setView('table')">Table</a>
  `,
  controller: function() {
    this.setView = function(view) {
      this.view = view
      this.onViewChange({$event: {view: view}})
    }
  },
  bindings: {
    view: '<',
    onViewChange: '&'
  }
})

ここで最も重要な部分はバインディングです。コンポーネントが外部の何かを読み取り、それを独自のコントローラーのプロパティとしてバインドできるように指定view: '<'します。コンポーネントで定義された出力: 必要なもので外界に通知/更新するためのチャネル。ヘッダー コンポーネントはこのチャネルを介してデータをプッシュしますが、親コンポーネントがそれをどう処理するかはわかりません。気にする必要はありません。headerviewonViewChange: '&'

したがって、headerコントローラーを次のように使用できることを意味します

<header-component view="root.view" on-view-change="root.view = $event.view"></header-component> 

主成分:入力。

メインコンポーネントはよりシンプルで、受け入れる入力を定義するだけで済みます:

.component('mainComponent', {
  template: `
    <h4>Main component</h4>
    Main view: {{ $ctrl.view }}
  `,
  bindings: {
    view: '<'
  }
})

親ビュー

そして最後に、すべてが一緒に配線されました:

<header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
<main-component view="root.view"></main-component>

簡単なデモを見て、遊んでください。

angular.module('demo', [])

.controller('RootController', function() {
  this.view = 'table'
})

.component('headerComponent', {
  template: `
    <h3>Header component</h3>
    <a class="btn btn-default btn-sm" ng-class="{'btn-primary': $ctrl.view === 'list'}" ng-click="$ctrl.setView('list')">List</a>
    <a class="btn btn-default btn-sm" ng-class="{'btn-primary': $ctrl.view === 'table'}" ng-click="$ctrl.setView('table')">Table</a>
  `,
  controller: function() {
    this.setView = function(view) {
      this.view = view
      this.onViewChange({$event: {view: view}})
    }
  },
  bindings: {
    view: '<',
    onViewChange: '&'
  }
})

.component('mainComponent', {
  template: `
    <h4>Main component</h4>
    Main view: {{ $ctrl.view }}
  `,
  bindings: {
    view: '<'
  }
})
<script src="https://code.angularjs.org/1.5.0/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />

<div class="container" ng-app="demo" ng-controller="RootController as root">
  
    <pre>Root view: {{ root.view }}</pre>
    
    <header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
    <main-component view="root.view"></main-component>
    
</div>

デモ: http://plnkr.co/edit/ODuY5Mp9HhbqA31G4w3t?p=info


コンポーネントベースの設計について詳しく説明したブログ投稿を次に示します: http://dfsq.info/site/read/angular-components-communication

于 2016-03-16T11:59:26.883 に答える
16

親コンポーネントのアプローチ (属性を介してデータを渡す) は完全に有効でありながら優れた実装ですが、ストアファクトリを使用して同じことをより簡単な方法で実現できます。

基本的に、データは によって保持され、Store両方のコンポーネント スコープで参照され、状態が変化したときに UI をリアクティブに更新できます。

例:

angular
    .module('YourApp')
    // declare the "Store" or whatever name that make sense
    // for you to call it (Model, State, etc.)
    .factory('Store', () => {
        // hold a local copy of the state, setting its defaults
        const state = {
            data: {
              heroes: [],
              viewType: 'grid'
            }
        };
        // expose basic getter and setter methods
        return {
            get() {
                return state.data;
            },
            set(data) {
                Object.assign(state.data, data);
            },
        };
    });

次に、コンポーネントには次のようなものが必要です。

angular
    .module('YourApp')
    .component('headerComponent', {
        // inject the Store dependency
        controller(Store) {
            // get the store reference and bind it to the scope:
            // now, every change made to the store data will
            // automatically update your component UI
            this.state = Store.get();

            // ... your code
        },
        template: `
            <div ng-show="$ctrl.state.viewType === 'grid'">...</div>
            <div ng-show="$ctrl.state.viewType === 'row'">...</div>
            ...
        `
    })
    .component('mainComponent', {
        // same here, we need to inject the Store
        controller(Store) {
            // callback for the switch view button
            this.switchViewType = (type) => {
                // change the Store data:
                // no need to notify or anything
                Store.set({ viewType: type });
            };

            // ... your code
        },
        template: `
            <button ng-click="$ctrl.switchViewType('grid')">Switch to grid</button>
            <button ng-click="$ctrl.switchViewType('row')">Switch to row</button>
            ...
        `

実際の例を見たい場合は、この CodePen をチェックしてください

そうすることで、2 つまたは N 個のコンポーネント間の通信を有効にすることもできます。次のことだけを行う必要があります。

  1. ストアの依存関係を注入する
  2. ストア データをコンポーネント スコープにリンクしていることを確認してください

上記の例のように ( <header-component>)。

現実の世界では、典型的なアプリケーションは大量のデータを管理する必要があるため、何らかの方法でデータ ドメインを論理的に分割する方が理にかなっています。同じアプローチに従って、さらに Store ファクトリを追加できます。たとえば、現在ログに記録されているユーザー情報と外部リソース (カタログなど) を管理するには、UserStoreプラス a CatalogStore-- またはUserModeland CatalogModel;を作成できます。これらのエンティティは、バックエンドとの通信、カスタム ビジネス ロジックの追加などを一元化するのにも適しています。その場合、データ管理はStore工場の単独の責任となります。

ストア データを変更していることに注意してくださいこのアプローチは非常にシンプルで明確ですが、副作用が発生するため、うまく拡張できない可能性があります。より高度なもの (不変性、純粋関数、単一状態ツリーなど)が必要な場合は、 Reduxを確認してください。最終的に Angular 2 に切り替えたい場合は、ngrx/storeをご覧ください。

お役に立てれば!:)

場合によっては移行する場合に備えて、Angular 2 の方法で行う必要はありません ...それを行うことが理にかなっている場合は、それを行います。

于 2016-10-25T13:56:10.857 に答える