【问题标题】:Computed property is only firing once计算属性只触发一次
【发布时间】:2019-04-28 13:03:52
【问题描述】:

我有一个名为 screen-size 的服务,它有一个名为 width 的属性。 此属性是窗口宽度的值,将在调整大小事件时更新。

这很好用。在一个组件中,我有一个计算属性,我想在这个值发生变化时更新它......

nameStyle: computed('screenSizeService.width', function()
{
    console.log('in computed');
    return this.getFontSize(2.5, 2, null, null, this.$())
}),

这只会在开始时运行一次,除非我这样做......

nameStyle: computed('screenSizeService.width', function()
{
    this.get('screenSizeService.width');
    console.log('in computed');
    return this.getFontSize(2.5, 2, null, null, this.$())
}),

然后它运行正常。 nameStyle的值与屏幕宽度没有直接关系,而是随着屏幕宽度的变化而变化的容器宽度。

这就是我从屏幕宽度读取的原因。

为什么我需要获取该值才能使其工作?为什么它不只是从它更改并运行该函数的时间开始计算?

【问题讨论】:

  • 哦,好的。但是如果我不需要它的价值呢?我只知道当它改变时,x 需要更新
  • observers 也许(从未使用过 ember,所以请谨慎接受我的建议)...
  • 我正在考虑使用观察者,只是听说了一些关于他们的坏事,还是试试看,谢谢!
  • @RachelDockter,不要使用观察者。相反,您可以使用events,请参阅我的回答。

标签: javascript ember.js


【解决方案1】:

我将尝试解释此案例并尝试提出一些替代解决方案。

说明

Ember Guides 说:

注入的属性是延迟加载的;这意味着在显式调用该属性之前不会实例化服务。

因此,如果您的应用程序不使用服务,则在您的应用程序开始使用该服务之前,该服务不会被实例化。

此外,如果您没有在组件中显式调用服务,那么您的组件将保留代理对象,直到您第一次调用/使用该服务。而这个代理并不是真正的服务对象。

所以在组件的第一次渲染中,由于您不使用screenSizeService,您将继续使用代理对象。因此,当真实对象发生变化时,您的计算无法重新计算。

但是当您使用/调用该服务时,您将开始使用真实对象,因此您的计算将能够绑定到真实服务对象的更改。在您的第二个代码中,此 touch 发生在 this.get('screenSizeService.width'); 行中。

替代方案

  1. 第一种选择是:在组件的 init/willRender 等钩子中触摸服务。如:
  init() {
    this._super(...arguments);
    // The following line added to initialize the service reference
    this.get('screenSizeService.width');
  }
  1. 第二种选择是:使用events。见Evented API 实际上,如果您不需要使用服务属性,但您需要从该服务接收通知;那么events 可以很好地适应。

在你的组件中你可以定义:

  init() {
    this._super(...arguments);
    this.get('screenSizeService').on('screenSizeChanged', ()=>{
      this.set('nameStyle', this.getFontSize(2.5, 2, null, null, this.$()))
    })
  }

在您的服务中,您需要在宽度值发生变化时使用:this.trigger('screenSizeChanged') 触发它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    相关资源
    最近更新 更多