PlayCanvas的EventHandler.on函数修改了返回值导致链式调用无法进行
链式调用
// Add pc.Application#tween methodpc.AppBase.prototype.tween = function (target) {return new pc.Tween(target, this._tweenManager);};
链式调用
var self = this
self.tweenFadeIn = self.app.tween(self.alpha)
.to(new pc.Vec3(1,0,0), self.fadeInTime, pc.Linear)
.on('update', function (dt) {for (var i = 0; i < self.images.length; i++) {self.images[i].element.opacity = self.alpha.x;}for (var i = 0; i < self.materials.length; i++) {self.materials[i].resource.opacity = self.alpha.x;self.materials[i].resource.update();}
})
.on('complete', function () {// 完成后的逻辑
});
PlayCanvas最近升级后,调用以上函数显示报错:
this.tweenFadeIn.start is not a function
在 JavaScript 中,方法链的写法通常是可以的,但在某些情况下,可能会因为上下文或返回值的问题导致链式调用失败。根据你提供的两种写法,第一种和第二种写法在逻辑上是相似的,但它们的效果取决于 self.app.tween(self.alpha) 返回的对象。
关键点
链式调用:在第一种写法中,self.app.tween(self.alpha) 返回的对象必须支持链式调用,也就是说,它的 to 和 on 方法应该返回 this,以便可以继续进行链式调用。
返回值:确保 self.app.tween(self.alpha) 返回的对象(即 Tween 实例)在调用 to 和 on 方法后没有被修改,仍然可以继续进行链式调用。
上下文问题:在某些情况下,this 的上下文可能会发生变化。如果你在链式调用中使用了不同的上下文(例如在某个回调函数中),可能会导致 this 指向错误的对象。
.on函数是在PlayCanvas的js库中定义的,查询event-handler.js,源代码摘录如下:
on(name, callback, scope = this) {return this._addCallback(name, callback, scope, false);}_addCallback(name, callback, scope, once) {// #if _DEBUGif (!name || typeof name !== 'string' || !callback)console.warn(`EventHandler: subscribing to an event (${name}) with missing arguments`, callback);// #endifif (!this._callbacks.has(name))this._callbacks.set(name, []);// if we are adding a callback to the list that is executing right now// ensure we preserve initial list before modificationsif (this._callbackActive.has(name)) {const callbackActive = this._callbackActive.get(name);if (callbackActive && callbackActive === this._callbacks.get(name)) {this._callbackActive.set(name, callbackActive.slice());}}const evt = new EventHandle(this, name, callback, scope, once);this._callbacks.get(name).push(evt);return evt;}
_addCallback返回的不再是this,而是event,所有导致链式调用中断。需要将链式调用修改如下:
self.tweenFadeIn = self.app.tween(self.alpha);
self.tweenFadeIn.to(new pc.Vec3(1, 0, 0), self.fadeInTime, pc.Linear);
self.tweenFadeIn.on('update', function (dt) {for (var i = 0; i < self.images.length; i++) {self.images[i].element.opacity = self.alpha.x;}for (var i = 0; i < self.materials.length; i++) {self.materials[i].resource.opacity = self.alpha.x;self.materials[i].resource.update();}
});
self.tweenFadeIn.on('complete', function () {// 完成时的逻辑
});
修改以后调用就正确了。