【问题标题】:HTML button onclick performs action on other HTML pageHTML 按钮 onclick 在其他 HTML 页面上执行操作
【发布时间】:2020-10-26 10:46:16
【问题描述】:

这是一个简单的问题,但我无法解决它,因为我是 Angular 和 Web 开发的新手。基本上有两个组件主页和仪表板。 home.component.html 中的按钮将图像的来源从bulbOn.png 更改为bulbOff.png。我希望同一个按钮也应该在dashboard.component.html上类似地更改源。我想我需要为此使用打字稿,但我不知道如何。基本上一个html上的onClick应该如何对另一个html执行操作?

home.component.html

<mat-card >              
              <button onclick="document.getElementById('myImage').src='assets/BulbOn.svg'">Turn on the bulb.</button>
              
              <img id="myImage" src="assets/BulbOn.svg" style="width:100px">
              
              <button onclick="document.getElementById('myImage').src='assets/BulbOff.svg'">Turn off the bulb.</button>
              
              </mat-card>

dashboard.component.html

<mat-card class="bulbCard">
    <div class="bulbimg"> <img src="assets/BulbOn.svg"> </div>
    </mat-card>

dashboard.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.less']
})
export class DashboardComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

home.component.ts

import { Component } from '@angular/core';
import { User } from '@app/_models';
import { AccountService } from '@app/_services';

@Component({ templateUrl: 'home.component.html',
styleUrls: ['./home.component.less'] })
export class HomeComponent {
    user: User;

    constructor(private accountService: AccountService) {
        this.user = this.accountService.userValue;
    }
}

【问题讨论】:

    标签: javascript html css angular typescript


    【解决方案1】:

    你应该避免像这样使用 Angular 操作 DOM。

    您应该使用 Angulars 事件绑定,而不是使用 onclick。 https://angular.io/guide/event-binding

    <mat-card>              
        <button (click)="changeBulbState(true)">
            Turn on the bulb.
        </button>
                  
        <img [src]="bulbState ? 'assets/BulbOn.svg' : 'assets/BulbOff.svg'" style="width:100px">
                  
        <button (click)="changeBulbState(false)">
            Turn off the bulb.
        </button>
                  
    </mat-card>
    

    在您的组件的打字稿中,为bulbState 添加一个变量。当您与卡片中的按钮交互时,其值会发生变化。

    图片的src会根据bulbState变量是真还是假而改变。

    import { Component } from '@angular/core';
    import { User } from '@app/_models';
    import { AccountService } from '@app/_services';
    
    @Component({ templateUrl: 'home.component.html',
    styleUrls: ['./home.component.less'] })
    export class HomeComponent {
        user: User;
    
        bulbState: boolean;
    
        constructor(
            private accountService: AccountService,
            private bulbStatusService: BulbStatusService
        ) {
            this.user = this.accountService.userValue,
            this.bulbStatusService.bulbStatus.subscribe(data => this.bulbState = value)
        }
    
        changeBulbState(state: boolean) {
            this.bulbStatusService.changeBulbState(state);
        }
    
    }
    

    为了在多个组件之间共享此内容,我建议使用服务。

    https://medium.com/front-end-weekly/sharing-data-between-angular-components-f76fa680bf76

    import { Injectable } from '@angular/core';
    import { BehaviorSubject } from 'rxjs';
    
    @Injectable()
    export class BulbStatusService {
    
      private bulbState = new BehaviorSubject(false);
      bulbStatus = this.bulbState.asObservable();
    
      constructor() { }
    
      changeBulbState(state: boolean) {
        this.bulbState.next(state)
      }
      
    }
    

    【讨论】:

    • 我尝试按照您使用布尔变量解释的方式进行操作,但对我不起作用。
    • 我已经对其进行了重构,以向您展示如何使用服务来控制状态并在组件之间共享它。您还需要将bulbStatusService 添加到您的仪表板组件并订阅它的更改。
    【解决方案2】:

    您希望在某处拥有一个灯泡状态。通常在 Angular 中,它要么是父组件将状态传递给它的子组件,要么你可以有一个服务来获取/设置状态。 RxJS 与 Angular 捆绑在一起,并且有一些很棒的实用程序(可观察对象)用于共享状态。

    例如app-state.service.ts

    import { BehaviorSubject } from 'rxjs'; 
    
    @Injectable({
      providedIn: 'root'
    })
    export class AppState {
       public readonly lightBulb = new BehaviorSubject<'on' | 'off'>('on');
    }
    

    现在将这个注入你的 home 组件:

    import { Component } from '@angular/core';
    import { User } from '@app/_models';
    import { AccountService } from '@app/_services';
    import { AppState } from 'app-state.service';
    
    @Component({ templateUrl: 'home.component.html',
    styleUrls: ['./home.component.less'] })
    export class HomeComponent {
        user: User;
    
        constructor(
            private accountService: AccountService,
            public state: AppState
        ) {
            this.user = this.accountService.userValue;
        }
    }
    

    在 HTML 中:

    <mat-card>              
      <button (click)="state.lightBulb.next('on')">Turn on the bulb.</button>
      <img id="myImage" [src]="(state.lightBulb | async) === 'on' ? 'assets/BulbOn.svg' : 'assets/BulbOff.svg'" style="width:100px">
      <button (click)="state.lightBulb.next('off')">Turn off the bulb.</button>
    </mat-card>
    

    然后对仪表板组件做同样的事情:

    import { Component } from '@angular/core';
    import { AppState } from 'app-state.service';
    
    @Component({
      selector: 'app-dashboard',
      templateUrl: './dashboard.component.html',
      styleUrls: ['./dashboard.component.less']
    })
    export class DashboardComponent {
    
      constructor(public state: AppState) { }
    }
    

    在 HTML 中:

    <mat-card class="bulbCard">
        <div class="bulbimg"><img [src]="(state.lightBulb | async) === 'on' ? 'assets/BulbOn.svg' : 'assets/BulbOff.svg'"></div>
    </mat-card>
    

    因此,简而言之,Subjects 是具有某些价值的事物,并且可以使用 Subject.next([value here]) 更改该价值。

    Subjects 是 Observables 和 Observables 可以是 subscribed 以随着时间的推移获得这些值。在 Angular 中,我们有 async 管道,它为您执行此订阅,并在组件被销毁后处理它。

    使用这种“可观察存储模式”,您可以做得更好,但这是最简单的形式。

    与其他事情相关的一些注意事项:使用(click) 而不是onclick 因为() 是Angular 绑定输出的方式。不要直接操作(或至少避免)DOM 中的任何内容,例如'document.getElementById('myImage').src='assets/BulbOn.svg'' 而是将该属性的值与[] 绑定,例如[bulbSvgSource] 其中“bulbSvgSource”将在组件类中定义。

    【讨论】:

    • 我认为这是我正在寻找的解决方案,但我在 app-state.service.ts 中遇到了一些错误。我生成了服务,但它说了以下内容,我太菜鸟无法理解它 - (别名)新 BehaviorSubject(_value: unknown): BehaviorSubject import BehaviorSubject Expected 1 arguments, but got 0.ts(2554 ) BehaviorSubject.d.ts(12, 17):未提供“_value”的参数。算术运算的左侧必须是“any”、“number”、“bigint”类型或枚举类型。ts(2362) 运算符“”跨度>
    • 是不是因为我在 new BehaviorSubject 中有错字('开');?应该是新的 BehaviorSubject('开');
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2011-05-10
    • 1970-01-01
    • 2013-04-07
    相关资源
    最近更新 更多