【问题标题】:IE not calling lifecycle hooks or filling @Input until change detected?IE 不调用生命周期挂钩或填充 @Input 直到检测到更改?
【发布时间】:2016-05-11 15:09:27
【问题描述】:

我使用 beta.0 是因为 this outstanding bug 阻止 Angular 2 在 IE 中的 beta.1 和 beta.2 中工作。

SearchBar.ts 中的相关代码

@Component({
  selector : 'search-bar',
  templateUrl: 'views/searchbar.html'
})
export class SearchBar {
  private history: SearchHistoryEntry[] = [];

  @Output() onHistory = new EventEmitter();

  constructor() {
    this.history = JSON.parse(localStorage.getItem('SearchHistory')) || [];
  }

  ngOnInit() {
    // The constructor doesn't have @Outputs initialized yet. Emit from this
    // life cycle hook instead to be sure they're received on the other side
    debugger;
    this.onHistory.emit(this.history);
  }
}

来自home.html的相关代码

<search-bar (onHistory)="SearchBarHistory($event)"></search-bar>

home.ts 中的相关代码

SearchBarHistory(history: SearchHistoryEntry[]) {
  debugger;
  this.history = history;
}

在 Chrome 中这工作得很好。 SearchBar 的构造函数正确地从localStorage 读取,在ngOnInit 中它发出给接收它的我的 Home 组件,它存储在本地,并且绑定到history 的 UI 绑定更新以显示所有应有的信息。

在 IE 11 中这不起作用。 ngOnInit 在我点击搜索栏后才会运行。似乎任何@Input 或生命周期挂钩(特别是我已经测试过ngOnInitngAfterContentInitngAfterViewInit 并且它们的行为都相同)在触发组件的更改检测之前不会运行。如果我刷新页面,那么它的运行方式与 Chrome 完全一样,@Inputs 或生命周期钩子无需交互即可调用,并且我的历史记录会按照应有的方式进行绑定。

我认为这是测试版的一个错误,但与此同时,我可以做些什么来让它在没有交互或页面刷新的情况下第一次工作?

【问题讨论】:

  • 用打字稿写这个例子与问题无关。最后编译成JS,问题依旧存在。我要删除 typescript 标签。

标签: internet-explorer-11 angular


【解决方案1】:

我也遇到了这个问题,我用了一个变通方法,如果出现这个bug,我会自动刷新页面,希望the bug最终能得到解决。

它非常丑陋,但至少现在它可以工作。

declare var Modernizr: any;

@Component({
  selector : 'search-bar',
  templateUrl: 'views/searchbar.html'
})
export class SearchBar {
  private history: SearchHistoryEntry[] = [];

  @Output() onHistory = new EventEmitter();

  ie11hack: boolean = true;

  constructor() {
    this.history = JSON.parse(localStorage.getItem('SearchHistory')) || [];

    if (!Modernizr.es6collections || navigator.userAgent.toLowerCase().indexOf("safari") !== -1) {

      setTimeout(() => {
        if (this.ie11hack) {
          window.location.reload();
        }
      }, 500);
    }
  }

  ngOnInit() {
    ie11hack = false;
    // The constructor doesn't have @Outputs initialized yet. Emit from this
    // life cycle hook instead to be sure they're received on the other side
    debugger;
    this.onHistory.emit(this.history);
  }
}

编辑,一个不那么难看的部分修复:

问题是(我认为)由使用直接 url 而不是使用 angular 路由器 (javascript) 引起的。 如果您希望您的网站在人们手动输入他们的网址时正常工作,那么您仍然需要上述技巧,否则您可以执行我在下面所做的操作(无论如何您可能都想这样做)。

我改变了这个:

<!-- html -->
<a href="#/objects/objectthingy/{{myObject.id}}" class="my-object-class">

到这里:

<!-- html -->
<a href="javascript:void(0)" (click)="openMyObject(myObject.id)" class="my-object-class">

// typescript
openMyObject(objectId: number) {
    this.router.navigate(['/Objects', 'ObjectThingy', { id: objectId}]);
}

ngAfterViewInit 方法再次被调用。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,我尝试通过强制检测更改来解决,例如:

    import {Injectable,ApplicationRef, NgZone} from '@angular/core';
    @Injectable()
    export class IeHackService {
    
    constructor(
        private _appRef: ApplicationRef,
        private _zone: NgZone) {}
    
    private isIe() {
        let ua = window.navigator.userAgent;
        let msie = ua.indexOf('MSIE ');
        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer, return version number
            return true;
        return false;
    }
    
    onComponentLoadInIe() {
        if (this.isIe()) {
            this._zone.run(() => setTimeout(() => this._appRef.tick(), 5));
        }
    }
    }
    

    然后在我调用的每个使用 Lifecycle Hooks 的 Route 组件中

       constructor(private dialogService: ModalDialogService,ieHackService: IeHackService) {
        ieHackService.onComponentLoadInIe();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-19
      • 1970-01-01
      • 2017-12-06
      • 2016-05-27
      • 2017-06-07
      • 1970-01-01
      相关资源
      最近更新 更多