我在我的Angular 4项目中包括了cropper.js。在组件中,我使用cropper.js,我注册了其ready
事件,如:
this.cropperOptions = {
// omitted options which are not importent
cropend: () => {
this.changedOrTouched();
},
ready: () => {
URL.revokeObjectURL(this.cropperImage.nativeElement.src);
this.photoReady.emit();
this.changedOrTouched();
}
};
发出的ready
事件由父部件消费,该事件本身通知服务
parent-component
photoReady(): void {
this.loaderService.setLoaderStatus(false);
}
服务
export class LoaderService {
public loaderStatus: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/**
* indicates wheter something in the application is loading or not. Internal it calls next() on the loaderStatus BehaviorSubject.
* This triggers any subscription to that BehaviorSubject which then can act.
* @param value true if application is loading, false if not.
*/
setLoaderStatus(value: boolean) {
this.loaderStatus.next(value);
}
}
app.component
订阅SO
app.component
this.loaderService.loaderStatus.subscribe((val: boolean) => {
this.isLoading = val;
//this is here because of iOS
this.changeDetector.detectChanges();
});
它的作用是显示或隐藏旋转器。
几乎每个浏览器都按预期工作,Execpt IE10在由Cropper.js Ready事件触发时不会隐藏旋转器。
当Zone.js仍然对我来说仍然是一个谜
我已经有类似的问题,我(或其他人)通常可以通过使用ChangeDetectorRef.detectChanges()
,NgZone.run()
ApplicationRef.tick
或在setTimeout
中包装呼叫来解决。
已经在各个地方尝试过这些问题,但我不明白为什么以上都没有解决问题。也许cropper.js添加了Zone.js无法处理的事件?也许有一种方法可以从外部JS库自定义事件?
有什么想法?
以下是cropper.js
添加事件的方式 cropper.js-添加事件
function addListener(element, type, _handler, once) {
var types = trim(type).split(REGEXP_SPACES);
var originalHandler = _handler;
if (types.length > 1) {
each(types, function (t) {
addListener(element, t, _handler);
});
return;
}
if (once) {
_handler = function handler() {
for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
removeListener(element, type, _handler);
return originalHandler.apply(element, args);
};
}
if (element.addEventListener) {
element.addEventListener(type, _handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, _handler);
}
}
cropper.js-派遣事件
function dispatchEvent(element, type, data) {
if (element.dispatchEvent) {
var event = void 0;
// Event and CustomEvent on IE9-11 are global objects, not constructors
if (isFunction(Event) && isFunction(CustomEvent)) {
if (isUndefined(data)) {
event = new Event(type, {
bubbles: true,
cancelable: true
});
} else {
event = new CustomEvent(type, {
detail: data,
bubbles: true,
cancelable: true
});
}
} else if (isUndefined(data)) {
event = document.createEvent('Event');
event.initEvent(type, true, true);
} else {
event = document.createEvent('CustomEvent');
event.initCustomEvent(type, true, true, data);
}
// IE9+
return element.dispatchEvent(event);
} else if (element.fireEvent) {
// IE6-10 (native events only)
return element.fireEvent('on' + type);
}
return true;
}
cropper.js-呼叫准备事件
// Call the "ready" option asynchronously to keep "image.cropper" is defined
self.completing = setTimeout(function () {
if (isFunction(options.ready)) {
addListener(element, EVENT_READY, options.ready, true);
}
dispatchEvent(element, EVENT_READY);
dispatchEvent(element, EVENT_CROP, self.getData());
self.complete = true;
}, 0);
cropper.js
与zone.js
不使用的原因是cropper.js
addeventListener/removeEventListener not patched by
Zone.js , so it is not in
ngzone`,您可以自己修补。
- 将
zone.js
更新到最新版本0.8.18 - 添加以下代码
Zone.__load_patch("cropper", function(global, Zone, api) {
// check cropper loaded or not
if (!global["cropper"]) {
return;
}
api.patchEventTarget(global, [global["cropper"].prototype], {
addEventListenerFnName: "addListener",
removeEventListenerFnName: "removeListener"
});
});
注意:该代码假定Cropper是一个全局对象,如果不是全球对象,请获取Cropper类型并替换全局[Cropper']部分。