代码之家  ›  专栏  ›  技术社区  ›  Get Off My Lawn

变量更改时,BehaviorSubject不会执行

  •  0
  • Get Off My Lawn  · 技术社区  · 4 年前

    我不确定我是否理解 BehaviorSubject ,但我想做的是观察一个变量的变化,这个变量是 双向绑定变量 附于 <input type="file"> 。当输入更改时,我想执行一个自动上传文件的函数。

    <input type="file" [(ngModel)]="presentationService.fileSelected">
    

    我使用的组件看起来像这样:

    @Component({
        selector: '...',
        templateUrl: '...'
    })
    export class CreatePresentationStep1 {
        public constructor(public presentationService: PresentationService) { }
    }
    

    服务看起来像这样:

    @Injectable()
    export class PresentationService {
        public fileSelected?: File;
    
        public constructor() {
            this.handlers();
        }
    
        private handlers(): void {
            new BehaviorSubject<File>(this.fileSelected).subscribe({
                next: (file) => {
                    console.log('file', file);
                }
            });
        }
    }
    

    加载组件时,控制台日志会运行并打印 file undefined ,这是正确的。当我点击输入字段并选择一个文件时,该行为再也不会运行。这是故意的吗?由于变量发生了变化,我预计调用会再次运行。如何让我的行为在每次变量更改时都运行?

    0 回复  |  直到 4 年前
        1
  •  3
  •   Poul Kruijt    4 年前

    这并不是真的 BehaviorSubject 作品。你在构造函数中传递的只是默认的初始值。它无法监视属性。在您的情况下,此代码应该可以工作:

    <input type="file" [ngModel]="presentationService.fileSelected$ | async" 
           (ngModelChange)="presentationService.fileSelected$.next($event)">
    
    @Component({
        selector: '...',
        templateUrl: '...'
    })
    export class CreatePresentationStep1 {
      constructor(public presentationService: PresentationService) { }
    }
    
    @Injectable()
    export class PresentationService {
        public readonly fileSelected$ = new BehaviorSubject<File | void>(void 0);
    
        public constructor(private _httpClient: HttpClient) {
            this.handlers();
        }
    
        private handlers(): void {
          this.fileSelected$.subscribe({
            next: (file) => {
              console.log('file', file);
            }
          });
        }
    }
    

    虽然这并不完全像我会做的那样。这给了你的消费者 PresentationService 完全访问主题/可观察对象,但这是一种方式:)

        2
  •  0
  •   Yuchao Wu    4 年前

    试试这个:

    <input type="file" (change)="fileChangeEvent($event)">

    在组件中绑定事件侦听器:

    @Component({
        selector: '...',
        templateUrl: '...'
    })
    export class CreatePresentationStep1 {
        public constructor(public presentationService: PresentationService) { }
        public fileChangeEvent(fileInput: any) {
          const file = fileInput.target.files[0];
          this.presentationService.handlers(file).subscribe(file => console.log('file', file));
       }
    }
    

    在服务中:

    @Injectable()
    export class PresentationService {
        public fileSelected?: File;
        private handlersSubject= new BehaviorSubject<File>(undefined);
        public handlerObs$ = this.handlersSubject.asObservable();
    
        public handlers(file: any): void {
            this.handlersSubject.next(file);
        }
    }