Angular 4,Zone.JS和JavaScript库的自定义事件



我在我的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.jszone.js不使用的原因是cropper.js addeventListener/removeEventListener not patched by Zone.js , so it is not in ngzone`,您可以自己修补。

  1. zone.js更新到最新版本0.8.18
  2. 添加以下代码
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']部分。

相关内容

  • 没有找到相关文章

最新更新