zoukankan      html  css  js  c++  java
  • ngRx 官方示例分析

     Page 中通过构造函数注入 Store,基于 Store 进行数据操作。

    注意 Component 使用了 changeDetection: ChangeDetectionStrategy.OnPush.

    OnPush means that the change detector's mode will be set to CheckOnce during hydration.

    /app/containers/collection-page.ts

    import 'rxjs/add/operator/let';
    import { Component, ChangeDetectionStrategy } from '@angular/core';
    import { Store } from '@ngrx/store';
    import { Observable } from 'rxjs/Observable';
    
    import * as fromRoot from '../reducers';
    import { Book } from '../models/book';
    
    
    @Component({
      selector: 'bc-collection-page',
      changeDetection: ChangeDetectionStrategy.OnPush,
      template: `
        <md-card>
          <md-card-title>My Collection</md-card-title>
        </md-card>
    
        <bc-book-preview-list [books]="books$ | async"></bc-book-preview-list>
      `,
      /**
       * Container components are permitted to have just enough styles
       * to bring the view together. If the number of styles grow,
       * consider breaking them out into presentational
       * components.
       */
      styles: [`
        md-card-title {
          display: flex;
          justify-content: center;
        }
      `]
    })
    export class CollectionPageComponent {
      books$: Observable<Book[]>;
    
      constructor(store: Store<fromRoot.State>) {
        this.books$ = store.select(fromRoot.getBookCollection);
      }
    }

    /app/containers/find-book-page.ts

    import 'rxjs/add/operator/let';
    import 'rxjs/add/operator/take';
    import { Component, ChangeDetectionStrategy } from '@angular/core';
    import { Store } from '@ngrx/store';
    import { Observable } from 'rxjs/Observable';
    
    import * as fromRoot from '../reducers';
    import * as book from '../actions/book';
    import { Book } from '../models/book';
    
    
    @Component({
      selector: 'bc-find-book-page',
      changeDetection: ChangeDetectionStrategy.OnPush,
      template: `
        <bc-book-search [query]="searchQuery$ | async" [searching]="loading$ | async" (search)="search($event)"></bc-book-search>
        <bc-book-preview-list [books]="books$ | async"></bc-book-preview-list>
      `
    })
    export class FindBookPageComponent {
      searchQuery$: Observable<string>;
      books$: Observable<Book[]>;
      loading$: Observable<boolean>;
    
      constructor(private store: Store<fromRoot.State>) {
        this.searchQuery$ = store.select(fromRoot.getSearchQuery).take(1);
        this.books$ = store.select(fromRoot.getSearchResults);
        this.loading$ = store.select(fromRoot.getSearchLoading);
      }
    
      search(query: string) {
        this.store.dispatch(new book.SearchAction(query));
      }
    }

     注意,点击搜索之后,我们回派发一个 Search 的 Action,但是,在 Book 的 Reducer 中并不处理这个 Action, @ngrx/effect 将会监控这个 Action,进行异步处理。

    /app/containers/not-found-page.ts

    import { Component, ChangeDetectionStrategy } from '@angular/core';
    
    
    @Component({
      selector: 'bc-not-found-page',
      changeDetection: ChangeDetectionStrategy.OnPush,
      template: `
        <md-card>
          <md-card-title>404: Not Found</md-card-title>
          <md-card-content>
            <p>Hey! It looks like this page doesn't exist yet.</p>
          </md-card-content>
          <md-card-actions>
            <button md-raised-button color="primary" routerLink="/">Take Me Home</button>
          </md-card-actions>
        </md-card>
      `,
      styles: [`
        :host {
          text-align: center;
        }
      `]
    })
    export class NotFoundPageComponent { }

     通过 @Input() 参数将数据从页面传递给下面的 Component,事件从底层 Component 冒泡上来。

    /app/containers/selected-book-page.ts

    import { Component, ChangeDetectionStrategy } from '@angular/core';
    import { Store } from '@ngrx/store';
    import { Observable } from 'rxjs/Observable';
    
    import * as fromRoot from '../reducers';
    import * as collection from '../actions/collection';
    import { Book } from '../models/book';
    
    
    @Component({
      selector: 'bc-selected-book-page',
      changeDetection: ChangeDetectionStrategy.OnPush,
      template: `
        <bc-book-detail
          [book]="book$ | async"
          [inCollection]="isSelectedBookInCollection$ | async"
          (add)="addToCollection($event)"
          (remove)="removeFromCollection($event)">
        </bc-book-detail>
      `
    })
    export class SelectedBookPageComponent {
      book$: Observable<Book>;
      isSelectedBookInCollection$: Observable<boolean>;
    
      constructor(private store: Store<fromRoot.State>) {
        this.book$ = store.select(fromRoot.getSelectedBook);
        this.isSelectedBookInCollection$ = store.select(fromRoot.isSelectedBookInCollection);
      }
    
      addToCollection(book: Book) {
        this.store.dispatch(new collection.AddBookAction(book));
      }
    
      removeFromCollection(book: Book) {
        this.store.dispatch(new collection.RemoveBookAction(book));
      }
    }

    /app/containers/view-book-page.ts

    import '@ngrx/core/add/operator/select';
    import 'rxjs/add/operator/map';
    import { Component, OnDestroy, ChangeDetectionStrategy } from '@angular/core';
    import { ActivatedRoute } from '@angular/router';
    import { Store } from '@ngrx/store';
    import { Subscription } from 'rxjs/Subscription';
    
    import * as fromRoot from '../reducers';
    import * as book from '../actions/book';
    
    /**
     * Note: Container components are also reusable. Whether or not
     * a component is a presentation component or a container
     * component is an implementation detail.
     *
     * The View Book Page's responsibility is to map router params
     * to a 'Select' book action. Actually showing the selected
     * book remains a responsibility of the
     * SelectedBookPageComponent
     */
    @Component({
      selector: 'bc-view-book-page',
      changeDetection: ChangeDetectionStrategy.OnPush,
      template: `
        <bc-selected-book-page></bc-selected-book-page>
      `
    })
    export class ViewBookPageComponent implements OnDestroy {
      actionsSubscription: Subscription;
    
      constructor(store: Store<fromRoot.State>, route: ActivatedRoute) {
        this.actionsSubscription = route.params
          .select<string>('id')
          .map(id => new book.SelectAction(id))
          .subscribe(store);
      }
    
      ngOnDestroy() {
        this.actionsSubscription.unsubscribe();
      }
    }

    /app/containers/app.ts

    import 'rxjs/add/operator/let';
    import { Observable } from 'rxjs/Observable';
    import { Component, ChangeDetectionStrategy } from '@angular/core';
    import { Store } from '@ngrx/store';
    
    import * as fromRoot from '../reducers';
    import * as layout from '../actions/layout';
    
    
    @Component({
      selector: 'bc-app',
      changeDetection: ChangeDetectionStrategy.OnPush,
      template: `
        <bc-layout>
          <bc-sidenav [open]="showSidenav$ | async">
            <bc-nav-item (activate)="closeSidenav()" routerLink="/" icon="book" hint="View your book collection">
              My Collection
            </bc-nav-item>
            <bc-nav-item (activate)="closeSidenav()" routerLink="/book/find" icon="search" hint="Find your next book!">
              Browse Books
            </bc-nav-item>
          </bc-sidenav>
          <bc-toolbar (openMenu)="openSidenav()">
            Book Collection
          </bc-toolbar>
    
          <router-outlet></router-outlet>
        </bc-layout>
      `
    })
    export class AppComponent {
      showSidenav$: Observable<boolean>;
    
      constructor(private store: Store<fromRoot.State>) {
        /**
         * Selectors can be applied with the `select` operator which passes the state
         * tree to the provided selector
         */
        this.showSidenav$ = this.store.select(fromRoot.getShowSidenav);
      }
    
      closeSidenav() {
        /**
         * All state updates are handled through dispatched actions in 'container'
         * components. This provides a clear, reproducible history of state
         * updates and user interaction through the life of our
         * application.
         */
        this.store.dispatch(new layout.CloseSidenavAction());
      }
    
      openSidenav() {
        this.store.dispatch(new layout.OpenSidenavAction());
      }
    }
  • 相关阅读:
    css实现水平/垂直居中效果
    Mac 下用homebrew安装配置MongoDB
    阿里云ECS搭建node/mongodb开发环境及部署
    阿里云首次安装和部署nginx
    前端学习借鉴目录
    040.[转] 对于程序框架的理解
    039.[转] 基于 Kubernetes 和 Spring Cloud 的微服务化实践
    038.[转] JVM启动过程与类加载
    037.[转] springboot 配置多个数据源
    036.[转] JNDI 学习
  • 原文地址:https://www.cnblogs.com/haogj/p/6537286.html
Copyright © 2011-2022 走看看