在第一个实现中,我使用angular2而不使用服务器渲染来创建一个带有video.js库的web播放器,它是“videojs-resolution-switcher”插件。
我创建了一个指令,用于基于组件ngOnInitView初始化videojs元素,并直接在基本html文件(正文末尾)中加载js文件。
一切都是正确的,玩家按预期工作。
然后我开始设置angular2-universal和服务器渲染。使用“isBrowser”工具处理浏览器特定功能时出现了一些问题。
但是现在我遇到了videojs-resolution-switcher的问题。即使在浏览器控制台中使用旧配置,错误仍然是:
Unable to find plugin: videoJsResolutionSwitcher
this.updateSrc is not a function
TypeError: this.updateSrc is not a function
at Player.<anonymous> (http://localhost:3000/main.bundle.js:95154:22)
at Player.<anonymous> (http://localhost:3000/main.bundle.js:5555:14)
at Array.forEach (native)
at Player.<anonymous> (http://localhost:3000/main.bundle.js:5554:20)
at bound (http://localhost:3000/main.bundle.js:8285:15)
at ZoneDelegate.invokeTask (http://localhost:3000/main.bundle.js:128033:31)
at Object.onInvokeTask (http://localhost:3000/main.bundle.js:38985:37)
at ZoneDelegate.invokeTask (http://localhost:3000/main.bundle.js:128032:36)
at Zone.runTask (http://localhost:3000/main.bundle.js:127836:47)
at ZoneTask.invoke (http://localhost:3000/main.bundle.js:128086:38)
at data.args.(anonymous function) (http://localhost:3000/main.bundle.js:129197:25)
我试图在指令中要求videoJsResolutionSwitcher,但它返回空对象(因为它没有被导出)。然后我更改了插件代码以导出函数,但没有改变只是更新了关于updateSrc函数的错误。
我试图像这样导入js文件:
import '../../node_modules/videojs-resolution-switcher/lib/videojs-resolution-switcher.js';
但是在编译时,在videojs分辨率切换器代码中出现了关于“取消定义窗口”的错误。
videojs.ts指令:
import { Component, Directive, ElementRef, Input, Output, EventEmitter } from '@angular/core';
import { Subject } from 'rxjs/Rx';
let videojs = require('video.js');
import { isBrowser } from "angular2-universal";
@Component({
selector: '[hiVideoJs]',
host: {
class: 'video-js vjs-default-skin vjs-big-play-centered',
'[attr.poster]': 'poster'
},
template: ``
})
export class VideoJsDirective {
@Input()
private col;
@Input()
private poster;
@Input()
private sources: Array<string> = new Array<string>();
@Input()
private options: any = {};
@Input()
private mute: boolean = false;
@Input()
private endEvent: Subject<boolean>;
@Output()
private fullscreen: EventEmitter<{}> = new EventEmitter();
@Output()
private created: EventEmitter<{}> = new EventEmitter();
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
// require('videojs-resolution-switcher')();
let width;
if (isBrowser)
width = this.col.clientWidth - ($(this.col).outerWidth() - $(this.col).width());
else
width = this.col.clientWidth;
var that = this;
this.options.width = width;
this.options.nativeControlsForTouch = false;
this.options.plugins = {
videoJsResolutionSwitcher: {
default: 'high',
dynamicLabel: true
}
};
var that = this;
if (isBrowser) {
let player = videojs(this.element.nativeElement, this.options, function () {
this.updateSrc(that.sources);
this.muted(that.mute);
if (that.endEvent)
this.on('ended', a => {
that.endEvent.next(true);
});
this.controlBar.fullscreenToggle.on('click', a => {
that.fullscreen.emit(true);
});
this.controlBar.fullscreenToggle.on('touchstart', a => {
that.fullscreen.emit(true);
});
});
this.created.emit(player);
}
}
ngOnDestroy() {
console.log('destroyed');
videojs(this.element.nativeElement).dispose();
}
}
更新
在经过大量测试后,我解决了这个问题,删除了“let videojs = require('videojs');”并添加此自定义类型定义:
interface VideoJSStatic {
(id: any, options?: any, ready?: () => void): any;
}
declare var videojs:VideoJSStatic;
但我想从概念上了解这种行为的原因是什么?