Chrome 自动完成锁定输入,就像它们不可点击一样

Posted

技术标签:

【中文标题】Chrome 自动完成锁定输入,就像它们不可点击一样【英文标题】:Chrome autocomplete lock inputs like they are not clickable 【发布时间】:2020-01-31 17:16:32 【问题描述】:

我在 Chrome 中使用自动填充时遇到问题和非常奇怪的行为。当我登录然后从应用程序注销时,输入字段(电子邮件、密码)会自动完成,但字段看起来像是被冻结且不可点击。

此错误并非每次都会重现,它发生在 1/10 的情况下。 当字段自动完成时,我在注销时注意到,1 秒后输入中的字体变小,之后如果你点击输入,似乎你没有点击,没有任何反应,但是如果你输入一些文本(数字不起作用,保持像冻结)输入字段正常。

这是带有奇怪行为的 gif: https://gifyu.com/image/kTkX

我尝试设置 autocomplete="off" ,但不起作用。

我还匹配了输入字段中的所有 css 类,以查看是否有一些覆盖 css,但一切看起来都不错。

<form [formGroup]="loginForm">

<input id="emailHeader" type="text" formControlName="email" placeholder="E-mail">

<input #password type="password" formControlName="password" placeholder="Lozinka">
<input type="submit" (click)="executeLogin()"  value="Prijava">

</form> 

我希望字段在自动填充后不会被冻结。

public loginForm: FormGroup;
  public emailInput: ElementRef;
  public passwordInput: ElementRef;
  @ViewChild('email') set emailContent(content: ElementRef) 
    this.emailInput = content;
  
  @ViewChild('password') set passwordContent(content: ElementRef) 
    this.passwordInput = content;
  

  // UI helpers
  public showLoginForm: boolean;
  public showBalance: boolean;
  public player: PlayerModel = new PlayerModel();
  public balanceInfo: BalanceInfoModel = new BalanceInfoModel();
  public nxcsBalanceInfo: NXCSBalanceInfoModel = new NXCSBalanceInfoModel();
  public dialogType = DialogType;
  public customMessageError = '';

  // Store
  private headerState$: Observable<any>;
  private loginState$: Observable<any>;
  private playerState$: Observable<any>;
  private emailInput$: Observable<any>;
  private passwordInput$: Observable<any>;
  private balanceState$: Observable<any>;
  private headerSubscription: Subscription;
  private loginSubscription: Subscription;
  private playerSubscription: Subscription;
  private emailSubscription: Subscription;
  private passwordSubscription: Subscription;
  private balanceSubscription: Subscription;
  // tslint:disable-next-line:no-inferrable-types
  private leftMenu: string = '';
  // tslint:disable-next-line:no-inferrable-types
  private rightMenu: string = '';

  constructor(
    private authService: AuthService,
    private fb: FormBuilder,
    private store: Store<any>,
    private route: Router,
    private localStorageService: LocalStorageService,
    private playerService: PlayerService,
    private notificationService: NotificationService,
    private dialogService: DialogService,
    private helpers: HelpersService,
    private translateCode: TranslateCode,
        private promotionService: PromotionService,
    ) 
    this.loginForm = this.buildLoginForm();
  

  ngOnInit() 
    this.setupStore();
  

  ngAfterViewInit() 
    this.formEventsAfterViewInit();
  

  ngOnDestroy() 
    this.headerSubscription.unsubscribe();
    this.loginSubscription.unsubscribe();
    this.playerSubscription.unsubscribe();
    this.notificationService.closeConnection();
  

  public executeLogin() 
    if(!this.loginForm.valid) 
      this.customMessageError = this.translateCode.transform("EMPTY_INPUT_MESSAGE");
      return;
    

    this.authService.login(new LoginModel(...this.loginForm.value, details: this.helpers.sendSessionData()))
      .subscribe(
        data => 
          this.localStorageService.setUserAfterLogin(data.token);
          this.customMessageError = '';
          this.loginForm.reset();
          this.route.navigate(['/app/casino']);
        ,
        error => 
          error.message.includes('Račun je zaključan') ? this.store.dispatch(new PopupNotification(error.message)) : this.customMessageError = error.message
          this.addAfterErrorSubscription();
        
      );
  

  public openDialog(dialogType: string): void 
    switch (dialogType) 
      case DialogType.PAYMENT:
         this.openWithdrawalDialog()
        break;
      case DialogType.PAYMENT_DEPOSIT:
          this.checkRegistrationStep();
      break;
      case DialogType.TRANSACTION_HISTORY:
        this.store.dispatch(new OpenDialog(
          type: dialogType,
        ));
      break;
    
  

  public openInternalTransactionsDialog(): void 
    this.promotionService.getPromotionsByLocation('NXCS_DEPOSIT')
      .subscribe(
                data => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION,  promotions: data ),
        error => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION,  promotions: []),
      );
  

  public backToRegistrationStep() : void 
    switch (this.player.registrationStep) 
      case 1 :  this.route.navigate(['/auth/registration/step-two']);
                break;
      case 2 : this.route.navigate(['/auth/registration/step-three']);
                break;
      case 3 : this.route.navigate(['/auth/registration/step-four']);
                break;
      case 4 : this.route.navigate(['/auth/registration/step-five']);
                break;
      case 5 : this.route.navigate(['/auth/registration/step-six']);
                break;
      default : this.route.navigate(['/login']);
                break;
     
  

  public toggleMenu(dialog): void 
    if (dialog === 'left') 
      this.leftMenu = this.leftMenu === dialog ? '' : dialog;
    
    if (dialog === 'right') 
      this.rightMenu = this.rightMenu === dialog ? '' : dialog;
    
    this.dispatchShadow();
  

  private openWithdrawalDialog(_data: any = ): void 
    const playerRole = this.localStorageService.getPlayer()['profileRole'];

    if (playerRole  === 'WITHDRAWAL_DISABLED' && this.player.uploadedAdditionalInfo) 
      this.store.dispatch(new OpenNotification( type: NotificationType.WITHDRAWAL_DISABLED ));
      return;
    

    playerRole  === 'WITHDRAWAL_DISABLED' ?
    this.store.dispatch(new OpenNotification(type: NotificationType.MONEY_LAUNDERING)) :
    this.dialogService.openDialog(MENU_DIALOGS.WHITDRAWALS, _data);
  

  private openProceedToRegistration(): void 
    this.store.dispatch(new OpenNotification (type: NotificationType.PROCEED_REGISTRATION))
  

  private checkRegistrationStep(): void 
    if(this.player.registrationStep < 6) 
      this.openProceedToRegistration();
     else 
      this.dialogService.openDialog(MENU_DIALOGS.DEPOSITS, );
    
  

  private dispatchShadow(): void 
    if (this.leftMenu !== '') 
      this.store.dispatch(new OpenedLeftMenu());
      this.leftMenu = '';
    
    if (this.rightMenu !== '') 
      this.store.dispatch(new OpenedRightMenu());
      this.rightMenu = '';
    
  

  private buildLoginForm(): FormGroup 
    return this.fb.group(
      email: [
        '', Validators.compose([Validators.required, Validators.min(5)]),
      ],
      password: [
        '', Validators.compose([Validators.required, Validators.min(5)])
      ],
    );
  

  private loadBalance(): void 
    this.playerService.getPlayerBalance().toPromise()
      .then(data => this.store.dispatch(new SetPlayerBalance(balanceInfo: new BalanceInfoModel(data) )))
      .then(() => 
        if (this.player.externalId) 
          this.playerService.getNXCSPlayerBalance()
            .subscribe(
              data => this.store.dispatch(new SetPlayerNXCSBalance( nxcsBalanceInfo: new NXCSBalanceInfoModel(data) )),
              error => console.log(error),
            );
        
      );
  

  // Store methods
  private setupStore(): void 
    this.headerState$ = this.store.pipe(select('headerStore'));
    this.loginState$ = this.store.pipe(select('loginStore'));
    this.playerState$ = this.store.pipe(select('playerStore'));
    this.balanceState$ = this.store.pipe(select('balanceStore'));
    this.addSubscriptions();
  

  private formEventsAfterViewInit(): void 
    if (this.emailInput && this.passwordInput) 
      this.emailInput$ = fromEvent(this.emailInput.nativeElement, 'focus');
      this.passwordInput$ = fromEvent(this.passwordInput.nativeElement, 'focus');
      this.addFormEventsSubscriptions();
    
  

  private addFormEventsSubscriptions(): void 
      this.emailSubscription = this.emailInput$.subscribe(() => this.triggerEmailFocus());
      this.passwordSubscription = this.passwordInput$.subscribe(() => this.triggerPasswordFocus());
  

  private triggerEmailFocus(): void 
    this.emailInput.nativeElement.select();
    if (this.emailSubscription) 
      this.emailSubscription.unsubscribe();
    
  

  private triggerPasswordFocus(): void 
    this.passwordInput.nativeElement.select();
    if (this.passwordSubscription) 
      this.passwordSubscription.unsubscribe();
    
  

  private addSubscriptions(): void 
    this.addHeaderSubscription();
    this.addLoginSubscription();
    this.addPlayerSubscription();
    this.setBalanceSubscription();
  

  private addHeaderSubscription(): void 
    this.headerSubscription = this.headerState$
    .subscribe(headerState => this.showLoginForm = headerState !== HeaderActionTypes.LoginPage);
  

  private addLoginSubscription(): void 
    this.loginSubscription = this.loginState$
    .subscribe(loginState => 
      if (loginState) 
        this.loadBalance();
        this.notificationService.connect(localStorage.getItem('token'));
       else 
        this.notificationService.closeConnection();
      
      this.showBalance = loginState;
      this.formEventsAfterViewInit();
    );
  

  private addPlayerSubscription(): void 
    this.playerSubscription = this.playerState$
    .subscribe(playerData => this.player = playerData);
  

  private addAfterErrorSubscription(): void 
    this.passwordSubscription = this.passwordInput$.subscribe(() => 
      if (this.customMessageError !== '') 
        this.customMessageError = '';
        this.passwordSubscription.unsubscribe();
      
    );
  


【问题讨论】:

也发生在我身上,你的不是一个孤立的案例。 +1 您好,欢迎来到***!如果您从应用程序中提供一些(简化的)代码,会更容易为您提供帮助。 听起来有点像 JS 在呈现表单后仍在进行计算,并且一直阻塞 UI 直到它停止。您是在获取自动填充建议还是在表单可以工作之前必须等待的其他内容?因此,网络延迟会阻碍渲染? 哦,该死的,这不是你应该使用的角度形式,这里有很多可能出错的地方,@ViewChild 声明,我不确定它是否能工作.当您使用formControl 时,您不需要@ViewChild()。而且你的订阅太多了,这会产生内存泄漏和无限循环的高风险,很容易冻结 UI。 在这种情况下,总有一种简单的方法可以找到错误。创建没有听众或其他任何东西的简单表单。检查是否存在错误。如果它仍然存在于纯 html 中,则意味着它是 Chrome 错误。如果在您添加了一些听众后出现,则表示您的听众有问题。 【参考方案1】:

当您允许 Google Chrome 将您的登录凭据保存在任何表单上时,每次自动填充字段时都会出现此问题。第一次也让我很烦。 当我第一次遇到它时,我试着给它一两次,但我逐渐继续前进并接受它作为每个 chrome 用户都必须处理的没什么大不了的错误。 所以总而言之,它与您的代码无关。如果您想unfreeze 输入字段,请开始在其中输入内容以更改其值。 我希望,这可以帮助您和您的神经接受这种与浏览器相关的行为。

【讨论】:

【参考方案2】:

您是否尝试过使用a href 标签?我知道这是显而易见的事情,但有时我们会忘记做那样的事情。此外,您可以在 CSS 中使用 a:hover 标签。

【讨论】:

欢迎来到 Stack Overflow。谢谢您的答复。但是,它更接近于评论而不是答案。你可以在这里看到如何写一个好的答案。 ***.com/help/how-to-answer【参考方案3】:

我在 Angular 中遇到了同样的问题,并为这种情况找到了解决方法,在输入点击时重置输入字段的值似乎可以解决我的锁定问题。

HTML:

<input (click)="unfreezeInput($event)">

TS:

unfreezeInput(el) 
    // setting input value again makes it editable
    el.target.value = el.target.value;

【讨论】:

以上是关于Chrome 自动完成锁定输入,就像它们不可点击一样的主要内容,如果未能解决你的问题,请参考以下文章

求EXCEL VBA代码。单元格输入内容保存后自动锁定有内容单元格。下次打开后不可编辑。

如何让Chrome开机自动启动

删除 Chrome 自动完成的输入光标颜色?

pixel去除锁定图案

黑客教你自动控制浏览器,自动化脚本神器

谷歌浏览器chrome怎样实现间隔自动刷新网页