Ember:为什么在观察者触发时计算不触发?
Ember: Why does computed not fire when the observer does?
我很难理解这个问题 - 我正在处理继承的遗留代码,虽然这看起来应该非常简单,但事实并非如此。
在这个 app/pods/application/route.js 中,有一个 "welcome pack" 对象被服务器抓取,作为其中的一部分,有一个在欢迎包服务上调用的 setWp() 方法,它设置同一服务的 'wp' 值。 (是的,我知道您可以使用 "this.wp.set('wp', welcomePack)" 直接在服务上设置值,但正如我所说:继承遗留代码。)要点是,这应该触发值的更改。我对 wp.wp 的观察者正在开火,但不是我基于 wp.wp 的计算。有什么线索吗?
// app/pods/application/route.js
wp: inject('welcome-pack'),
model(){
return this.store.findAll('welcome-pack').then((welcomePack) => {
this.wp.setWp(welcomePack);
})
}
// app/pods/welcome-pack/service.js
import Service from '@ember/service';
export default Service.extend({
wp: null,
setWp(wp){ // <-- called when the model loads from the ajax request
this.set('wp', wp)
}
})
// app/pods/application/controller.js
import Controller from "@ember/controller";
import { inject } from "@ember/service";
import { computed, observer } from "@ember/object";
export default Controller.extend({
wp: inject("welcome-pack"),
init(){
console.log('this.wp', this.wp) // <- logs service as class
console.log('this.wp.wp', this.wp.wp) // <-logs null
setTimeout(() => {
// set for after the ajax call has been made and setWp() has been called.
console.log('this.wp', this.wp) //<- logs service as class
console.log('this.wp.wp', this.wp.wp) //<- logs object as class
}, 2000)
},
obsWPChanges: observer('wp', function(){
console.log('wp changed'); // <-- never executes (don't expect it to)
}),
obsWPWPChanges: observer('wp.wp', function(){
console.log('wp.wp changed') //<-- executes (as expected) when setWP() is called
}),
primaryColor: computed("wp.wp", function() {
console.log("this.wp.primaryColor", this.wp.primaryColor) // <-- does not execute
return this.wp.wp.primaryColor || "#37b3c0";
}),
secondaryColor: computed("wp.wp", function() {
return this.wp.wp.secondaryColor || "#38a0d0"; // <-- does not execute
})
});
在 Ember 中,计算属性是惰性求值的。因此,在引用它们之前,它们永远不会被执行。
另一方面,观察者总是在依赖键发生变化时触发。您上面显示的行为是完全可以解释的,假设 primaryColor
和 secondaryColor
从未被这个时间点引用。摘自docs:
A computed property will only recompute its value when it is consumed.
Properties are consumed in two ways:
By being accessed, for example ironMan.fullName
By being referenced in
a handlebars template that is currently being rendered, for example
{{ironMan.fullName}}
Outside of those two circumstances the code in
the property will not run, even if one of the property's dependencies
are changed.
我记得你在 Ember subreddit 上的长篇大论,希望你玩得开心。既然您已经积累了一些经验,我强烈建议您仔细阅读文档。
我很难理解这个问题 - 我正在处理继承的遗留代码,虽然这看起来应该非常简单,但事实并非如此。
在这个 app/pods/application/route.js 中,有一个 "welcome pack" 对象被服务器抓取,作为其中的一部分,有一个在欢迎包服务上调用的 setWp() 方法,它设置同一服务的 'wp' 值。 (是的,我知道您可以使用 "this.wp.set('wp', welcomePack)" 直接在服务上设置值,但正如我所说:继承遗留代码。)要点是,这应该触发值的更改。我对 wp.wp 的观察者正在开火,但不是我基于 wp.wp 的计算。有什么线索吗?
// app/pods/application/route.js
wp: inject('welcome-pack'),
model(){
return this.store.findAll('welcome-pack').then((welcomePack) => {
this.wp.setWp(welcomePack);
})
}
// app/pods/welcome-pack/service.js
import Service from '@ember/service';
export default Service.extend({
wp: null,
setWp(wp){ // <-- called when the model loads from the ajax request
this.set('wp', wp)
}
})
// app/pods/application/controller.js
import Controller from "@ember/controller";
import { inject } from "@ember/service";
import { computed, observer } from "@ember/object";
export default Controller.extend({
wp: inject("welcome-pack"),
init(){
console.log('this.wp', this.wp) // <- logs service as class
console.log('this.wp.wp', this.wp.wp) // <-logs null
setTimeout(() => {
// set for after the ajax call has been made and setWp() has been called.
console.log('this.wp', this.wp) //<- logs service as class
console.log('this.wp.wp', this.wp.wp) //<- logs object as class
}, 2000)
},
obsWPChanges: observer('wp', function(){
console.log('wp changed'); // <-- never executes (don't expect it to)
}),
obsWPWPChanges: observer('wp.wp', function(){
console.log('wp.wp changed') //<-- executes (as expected) when setWP() is called
}),
primaryColor: computed("wp.wp", function() {
console.log("this.wp.primaryColor", this.wp.primaryColor) // <-- does not execute
return this.wp.wp.primaryColor || "#37b3c0";
}),
secondaryColor: computed("wp.wp", function() {
return this.wp.wp.secondaryColor || "#38a0d0"; // <-- does not execute
})
});
在 Ember 中,计算属性是惰性求值的。因此,在引用它们之前,它们永远不会被执行。
另一方面,观察者总是在依赖键发生变化时触发。您上面显示的行为是完全可以解释的,假设 primaryColor
和 secondaryColor
从未被这个时间点引用。摘自docs:
A computed property will only recompute its value when it is consumed. Properties are consumed in two ways:
By being accessed, for example
ironMan.fullName
By being referenced in a handlebars template that is currently being rendered, for example
{{ironMan.fullName}}
Outside of those two circumstances the code in the property will not run, even if one of the property's dependencies are changed.
我记得你在 Ember subreddit 上的长篇大论,希望你玩得开心。既然您已经积累了一些经验,我强烈建议您仔细阅读文档。