Angular 2 Dart:如何在父组件与路由器和子组件之间共享变量?

Posted

技术标签:

【中文标题】Angular 2 Dart:如何在父组件与路由器和子组件之间共享变量?【英文标题】:Angular 2 Dart: How to share variables between parent with router and child components? 【发布时间】:2017-10-03 22:00:16 【问题描述】:

如果子组件带有路由器,我如何共享变量并通过绑定保持更新?

这是(部分)我的代码:

app_component.dart:

import 'package:angular2/core.dart';
import 'package:angular2_components/angular2_components.dart';
import 'package:angular2/router.dart';

import 'package:my_app/profile_component/profile_component.dart';
import 'package:my_app/login_component/login_component.dart';

@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html',
  directives: const [
    ROUTER_DIRECTIVES,
    materialDirectives,
    LoginComponent,
    ProfileComponent
  ],
  providers: const [
    ROUTER_PROVIDERS,
    const Provider(LocationStrategy, useClass: HashLocationStrategy),
    materialProviders
  ],
)
@RouteConfig(const [
  const Route(path: 'home', name: 'Home', component: HomeComponent, useAsDefault: true),
  const Route(path: 'profile', name: "User Profile", component: ProfileComponent)
])
class AppComponent 

  @ViewChild('login')
  LoginComponent loginComponent;
  @ViewChild('profile')
  ProfileComponent profileComponent;

  bool get isUserLoggedIn => loginComponent.isUserLoggedIn;


app_component.html:

<nav>
    <ul>
    <li *ngIf="!isUserLoggedIn">
        <a (click)="loginComponent.loginOpen=true">Account / Login</a>
    </li>
    <li *ngIf="isUserLoggedIn">
        <a id="mb_logout" (click)="loginComponent.logUserOut()">Logout</a>
    </li>
    <li *ngIf="isUserLoggedIn">
        <a id="mb_profile"  [routerLink]="['User Profile']">Zum Profil</a>
    </li>
    </ul>
</nav>

login_component.dart:

...
bool get isUserLoggedIn => _isUserLoggedIn();
...

profile_component.dart:

import 'package:angular2/core.dart';
import 'package:angular2_components/angular2_components.dart';

@Component(
  selector: 'profile',
  styleUrls: const ['profile_component.css'],
  templateUrl: 'profile_component.html',
  directives: const [materialDirectives],
  providers: const [materialProviders],
)
class ProfileComponent 

  @Input()
  bool isUserLoggedIn;

  ProfileComponent() 
    print(isUserLoggedIn);
  

简而言之,我想从 ProfileComponent 中访问 isUserLoggedIn 的当前值。我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

对父组件提供共享服务

@Injectable()
class SharedService 
  bool _isUserLoggedIn = false;
  bool get isUserLoggedIn => _isUserLoggedIn;
  set isUserLoggedIn(bool value) 
    _isUserLoggedIn = value ?? false;
    _isUserLoggedInController.add(_isUserLoggedIn);
  

  StreamController<bool> _isUserLoggedInController;
  Stream<bool> get onIsUserLoggedIn => _isUserLoggedInController.stream;


  SharedService() 
     _isUserLoggedInController = new StreamController<bool>.broadcast(
       onListen: () => _isUserLoggedInController.add(_isUserLoggedIn)
     );
  

在要更新的组件中使用或更新状态注入服务

@Component(
  ...,
  template: '''
    <div>isLoggedIn: sharedService.onIsUserLoggedIn | async</div>
    <button (click)="toggleIsUserLoggedIn()">(sharedService.onIsUserLoggedIn | async) ? 'log out' : 'log in'</div>
  ''',
)
class SomeComponent 
  final SharedService sharedService;
  SomeComponent(this.sharedService);

  toggleIsUserLoggedIn() 
    sharedService.isUserLoggedIn = !sharedService.isUserLoggedIn;
  

AppComponent提供服务

@Component(
  selector: 'my-app',
  providers: const [SharedService],
)
class AppComponent 

【讨论】:

【参考方案2】:

这就是我实现这一目标的方式。使用共享服务。

在正在更新/使用模型的组件中:

class myClassSend 

 constructor(private sharedService: SharedService)
     this.sharedService.userStatusUpdate(this.isUserLoggedIn); // We send isUserLoggedIn value to the shared service

  

我们的共享服务可能是这样的:

export class SharedService 
  userStatusUpdate$: Observable<any>;
  private userStatusUpdateSubject = new Subject<any>();

  constructor() 
        this.userStatusUpdate$ = this.userStatusUpdateSubject.asObservable();
  

  userStatusUpdate(userStatus) 
        this.userStatusUpdateSubject.next(userStatus);
  

在我们想知道模型价值的组件中:

class myClassReceive 
  bool isUserLoggedIn;

 constructor(private sharedService: SharedService)
     this.sharedService.userStatusUpdate$.subscribe((userStatus) => 
           this.isUserLoggedIn = userStatus;  // And here we receive the isUserLoggedIn value!
            
        );

现在,想想你可以从myClassSend 随时发送信息:onInit、onChange 等...而myClassReceive 将一直“监听” 并将接收您作为参数发送到共享服务的值。

将共享服务想象成一个与两个人(组件)通信、发送消息(参数/数据)的手机。

这是 Angular 的文档:https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

【讨论】:

以上是关于Angular 2 Dart:如何在父组件与路由器和子组件之间共享变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 中显示具有自己路由的父组件内的特定子组件?

Dart 的 Web 组件与 Angular 的指令

Angular 1.5 父子组件问题

如何从父组件调用路由器出口子组件方法

如何在 Dart 2 中使用材质角镖组件的排版?

在Angular2 Dart中设置路由器和RouterLink的正确方法是啥