在持续生命周期回调中初始化第三方库

Inializing third-party library within durandal lifecycle callbacks

本文关键字:初始化 第三方 回调 周期 生命      更新时间:2023-09-26

我需要初始化第三方库- videojs -每次视图模型激活。然而,问题是库需要一个dom元素,当durandal的激活回调被执行时,它还没有被附加。

//viewmodel
define (["jquery", "knockout", "videojs"], function ($, ko, videojs) {
  var
    activate = function (videoSource) { //route param
      var videoTag = $('#video').get(0); //undefined
      var playerInstance = new videojs.Player(videoTag); //error
      playerInstance.src(videoSource); //loads video from route parameter
      playerInstance.play(); //starts to play
    };
    return {
      activate: activate
    }
});
//view
<section id="page-quiz-answer" class="page">
    <video id="video"></video>
</section>

DOM在#activate回调中还不可用。您需要在#attached或#compositionComplete回调中访问DOM元素。你可以在这里阅读这些回调函数的签名,以及它们的预期目的。

//viewmodel
define (["jquery", "knockout", "videojs"], function ($, ko, videojs) {
    var attached = function (view) { //route param
      var $view = $(view);
      var $videoTag = $view.find('#video'); //undefined
      var playerInstance = new videojs.Player($videoTag); //error
      playerInstance.src(videoSource); //loads video from route parameter
      playerInstance.play(); //starts to play
    };
    return {
      attached: attached
    }
});

另一种方法

您还可以编写一个自定义Knockout绑定,并封装访问DOM元素的逻辑。

我实际上会建议使用这种方法,因为我怀疑您将DOM引用传递给videojs.Player()的点。这需要在自定义绑定中封装。

[编辑]

自定义绑定的使用示例

在视图中考虑这种用法:

<div id='video' data-bind=player: {instance: playerInstance, source: videoSource}></div>
有了这个,您就可以将上面#attached函数中的所有逻辑移动到自定义绑定中。如果你需要动态控制playerInstance,你可以在视图模型中创建一个带有可观察属性的对象字面值,类似如下:
var playerOptions = {
        action: ko.observable('play'),
        player: new videojs.Player(),
        source: ko.observable(videoSource)
    };

并将绑定更改为:

<div id='video' data-bind=player: {options: playerOptions}></div>

你的自定义绑定看起来像这样:

ko.bindingHandlers.player = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var options = ko.unwrap(valueAccessor),
            $element = $(element);            
        var playerInstance = options.player;
        playerInstance.source = options.source();
        playerInstance.do(options.action());
    }
};

我不确定你的播放器是如何连接到DOM的。我只能看到您传入了一个DOM元素。但是在这个绑定中,您可以访问元素本身。