我有一个名为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的值与屏幕宽度没有直接关系,但是容器宽度会随着屏幕宽度的变化而改变。
这就是为什么我从屏幕宽度读取内容。
为什么我需要获取值才能使它起作用?为什么不从更改和运行该功能时开始计算呢?
答案 0 :(得分:1)
我将尽力解释这种情况,并尝试提出一些替代解决方案。
说明
注入的属性是延迟加载的;意味着在显式调用该属性之前,不会实例化该服务。
因此,如果您的应用程序不使用服务,则在您的应用程序开始使用该服务之前,不会实例化该服务。
此外,如果您没有明确调用组件中的服务,则组件将保留代理对象,直到您第一次调用/使用该服务。而且该代理不是真正的服务对象。
因此,在组件的第一个渲染中,由于您不使用screenSizeService
,因此将继续使用代理对象。因此,当真实对象更改时,您的计算结果将无法重新计算。
但是当您使用/调用该服务时,您将开始使用真实对象,因此您的计算对象将能够绑定到真实服务对象的更改。在您的第二个代码中,此touch
发生在this.get('screenSizeService.width');
行中。
解决方案
init() {
this._super(...arguments);
// The following line added to initialize the service reference
this.get('screenSizeService.width');
}
events
。参见Evented API
实际上,如果您不需要使用services属性,但是您需要从该服务接收通知;那么events
就可以很好地适应了。您可以在组件中定义:
init() {
this._super(...arguments);
this.get('screenSizeService').on('screenSizeChanged', ()=>{
this.set('nameStyle', this.getFontSize(2.5, 2, null, null, this.$()))
})
}
,并且在您的服务中,只要宽度值发生更改,您就需要使用this.trigger('screenSizeChanged')
来触发它。