首页 > 解决方案 > 为什么 Angular 5 组件通过明确的焦点刷新得更快?

问题描述

我编写了一个使用 Google Places Autocomplete 的自定义组件(下面的代码)。对于那些不熟悉的人,当用户在输入框中键入时,这会显示一个自动完成功能,他们可以使用它们来选择合格的地址。该组件工作正常,但是当它发出选择的地址时,需要几秒钟才能将新值绑定到父级中。如果我在发出地址的同时 focus() 输入框(参见下面代码中的最后一行),则立即绑定新值。为什么会这样,是否有更好的方法来确保新值立即被绑定?

需要明确的是,我不认为这个问题与地方自动完成本身有关,只是一些我不明白的 Angular 内部。

在父页面上:

<google-address-picker [(value)]="foo"></google-address-picker>
{{foo.fullAdress}} //Without focus() line below, this takes several seconds to populate.

组件代码:

import { Component, ElementRef, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'google-address-picker',
  templateUrl: 'google-address-picker.html'
})
export class GoogleAddressPickerComponent {

   autocomplete: any;
   googleAddressComponents: any = {};
   googlePlace: any = {};
   address: any = {};
   @Output() valueChange: EventEmitter<any> = new EventEmitter<any>();
   @Input() value: any = { fullAddress: '' };

   constructor(private elRef: ElementRef) {
   }

   ngAfterViewInit() {
      var self = this;
      var addressElement = 
      this.elRef.nativeElement.querySelector('.addressElement');
      var anyWindow: any = window;
      var google: any = anyWindow.google;
      this.autocomplete = new google.maps.places.Autocomplete(addressElement, {});
      self.autocomplete.addListener('place_changed', () => this.changed());
      addressElement.addEventListener('blur', function () {
         self.valueChange.emit(self.value);
       });
   }

    changed() {  
       var self = this;
       self.googlePlace = self.autocomplete.getPlace();  
       self.googleAddressComponents = {};
       self.address = { latitude: null, longitude: null, street: '', city: '', stateName: '', stateCode: '', zipCode: '', countryName: '', countryCode: '', fullAddress: '' };
       if (self.googlePlace && self.googlePlace.address_components) {
         for (var i = 0; i < self.googlePlace.address_components.length; i++) {
           var component = self.googlePlace.address_components[i];
           self.googleAddressComponents[component.types[0]] = component.long_name;
           if (component.short_name)
              self.googleAddressComponents[component.types[0] + '_code'] = component.short_name;
          }
         }
         if (self.googleAddressComponents.administrative_area_level_1) self.address.stateName = self.googleAddressComponents.administrative_area_level_1;
         if (self.googleAddressComponents.administrative_area_level_1_code && self.googleAddressComponents.administrative_area_level_1_code.length === 2) self.address.stateCode = self.googleAddressComponents.administrative_area_level_1_code;
         if (self.googleAddressComponents.country) self.address.countryName = self.googleAddressComponents.country;
         if (self.googleAddressComponents.country_code) self.address.countryCode = self.googleAddressComponents.country_code;
         if (self.googleAddressComponents.locality) self.address.city = self.googleAddressComponents.locality;
         if (self.googleAddressComponents.route) self.address.street = self.googleAddressComponents.route;
         if (self.googleAddressComponents.street_number) self.address.street = [self.googleAddressComponents.street_number, self.address.street].join(' ');
         if (self.googleAddressComponents.postal_code) self.address.zipCode = self.googleAddressComponents.postal_code;

         if (self.googlePlace && self.googlePlace.formatted_address)
  self.address.fullAddress = self.googlePlace.formatted_address;
         if (self.googlePlace && self.googlePlace.geometry && self.googlePlace.geometry.location) {
             self.address.latitude = self.googlePlace.geometry.location.lat();
             self.address.longitude = self.googlePlace.geometry.location.lng();
         }
         if (!self.value) self.value = {};    
         for (var key in self.address)
            self.value[key] = self.address[key];
         self.valueChange.emit(self.value);
         var addressElement = this.elRef.nativeElement.querySelector('.addressElement');
         addressElement.focus(); //Not sure why, but this triggers immediate Angular refresh.  Without, refresh can be several seconds.        
   };
  }

标签: angularweb-component

解决方案


推荐阅读