Javascript 角度5视图在超时后不更新

Javascript 角度5视图在超时后不更新,javascript,angular,asynchronous,Javascript,Angular,Asynchronous,我正在设置一个超时,以便在Angular 5中隐藏一个元素: this.showElement = true; setTimeout(function () { console.log('hide'); this.showElement = false; }, 2000); 但是,这不会更新视图。console.log为我提供了一个输出,因此超时确实有效 我发现在Angularjs中,你需要调用$apply来开始一个摘要,所以我猜我只需要找到Angularjs的5种等效方法。更新:正确

我正在设置一个超时,以便在Angular 5中隐藏一个元素:

this.showElement = true;
setTimeout(function () {
  console.log('hide');
  this.showElement = false;
}, 2000);
但是,这不会更新视图。
console.log
为我提供了一个输出,因此超时确实有效


我发现在Angularjs中,你需要调用
$apply
来开始一个摘要,所以我猜我只需要找到Angularjs的5种等效方法。

更新:正确答案。

正如其他人正确回答的那样,未反映更改的原因是对
引用的引用不正确

请注意,当使用
function(){…}
表示法时,对
this
的引用是函数本身的上下文。所以

myFunction() {
    this.showElement = true;
    setTimeout(function() {
      console.log(this.showElement); // Will result in undefined;
      this.showElement = false; // Here, this, reference to context of the function wrapper
    }, 2000);
}
将上述内容更改为ES6箭头表示法,会将
引用的上下文更改为父上下文。所以

myFunction() {
    this.showElement = true;
    setTimeout(() => {
      console.log(this.showElement); // Will result in true;
      this.showElement = false; // Here, value is updated
    }, 2000);
}

当您使用函数样式“this”引用不起作用时,请阅读有关
词法this

的更多信息 像下面这样做,您的示例将正确运行

this.showElement = true;
setTimeout(() => {
    console.log('hide');
    this.showElement = false;
}, 2000);

我认为
setTimeout
回调失去了“showElement”变量的作用域

this.showElement = true; // this - is in component object context
setTimeout(function () {
   console.log('hide');
   this.showElement = false; // here... this has different context
}, 2000);
应使用箭头功能:

this.showElement = true;
setTimeout(() => {
  console.log('hide');
  this.showElement = false;
}, 2000);
或者使用
bind

this.showElement = true;
setTimeout(function() {
  console.log('hide');
  this.showElement = false;
}.bind(this), 2000);

要将正确的上下文传递给
setTimeout
回调函数。

我在Angular 7应用程序中遇到了同样的问题。我必须更改按钮中标题和图标的来源:

<button class="btn btn--outline-red text-uppercase font-weight-normal product-action-btn mt-3"
              (click)="addToCart()">
              {{addToCartProps.title}}
              <img style="width:15px; height:15px;" [src]="addToCartProps.src">
            </button>
setTimeout(function () {
  console.log('hide');
  this.showElement = false;
}.bind(this), 2000);
this.showElement = true;
setTimeout(() => {
  console.log('hide');
  this.showElement = false;
}, 2000);
在timeout函数中添加this.cd.markForCheck()解决了我的问题


早些时候,@artemisian在您的构造函数中,添加了一个变更检测器,对其进行了评论:

constructor(private cd: ChangeDetectorRef) {}
然后在设置超时时:


它正在更新值,但问题在于
。您可以通过bind或arrow函数设置该值

setTimeout(function () {
  console.log('hide');
  this.showElement = false;
}.bind(this), 2000);
this.showElement = true;
setTimeout(() => {
  console.log('hide');
  this.showElement = false;
}, 2000);
或者我们可以使用arrow函数,因为它的这个值是包含函数的setup

setTimeout(function () {
  console.log('hide');
  this.showElement = false;
}.bind(this), 2000);
this.showElement = true;
setTimeout(() => {
  console.log('hide');
  this.showElement = false;
}, 2000);

您不需要进行更改检测,甚至不需要超时,只要将this.showElement双向绑定到元素本身上的*NgIf,它就会根据需要删除并显示它。当心超时使用,它可能会消耗资源,如果你想让应用程序通用,它会杀死你的应用程序。要补充的一点是,在Angular 1.x中,有一个$timeout服务你会使用。在Angular 2+中,没有$timeout服务。如果您希望保留组件/服务上下文的词法范围,则最好/建议使用arrow函数。如果在Ionic 4中存在相同的问题,这是正确的解决方案。