使用 Knockout 在 Durandal JS 框架中添加和运行 JQuery

Posted

技术标签:

【中文标题】使用 Knockout 在 Durandal JS 框架中添加和运行 JQuery【英文标题】:Add and run JQuery in Durandal JS framework using Knockout 【发布时间】:2018-04-23 05:12:22 【问题描述】:

在 ViewModel 中运行 JQuery 代码和在 View 中执行代码时遇到困难。该环境使用 Durandal JS 框架运行。不幸的是,从简单的alert('Hello?') 到运行 60 秒的计时器,任何东西都不起作用。计时器只停留在 59:59。没有任何 JQuery 代码正在工作/运行。甚至不是一个简单的$('h1').css('color','red');

如何在 Durandal / Knockout 视图中运行 JQuery?这是我尝试在我的视图中工作的功能计时器示例。

shell.html 计时器位于带有重置按钮的页脚下方。

<div class="wrapper">

    <!-- navigation -->
    <nav>
        <div class="container">...</div>
    </nav>
    <!-- end: navigation -->


    <!-- body -->
    <div class="container page-host" data-bind="router:  transition:'entrance' "></div>
    <!-- end: body -->


    <!-- footer -->
    <footer>
        <div class="container">
            <div class="row">

                <div class="col-xs-12">...</div>

            </div>
        </div>
    </footer>
    <!-- end: footer -->


    <!-- timer -->
    <div class="timer affix-top" data-spy="affix" data-offset-top="50">
        <span id="countdown">59:59</span>
        <p id="reset" tabindex="0">
            <strong class="hidden-sm hidden-xs">Click here to reset timer</strong>
            <strong class="hidden-lg hidden-md">Reset timer</strong>
        </p>
    </div>
    <!-- end: timer -->

</div>

shell.js JQuery 代码需要进入这里,但我尝试过的一切都不起作用。下面是运行计时器的 JQuery 代码。

define(['plugins/router', 'durandal/app'], function (router, app) 
    return 
        router: router,
        search: function() 
            //It's really easy to show a message box.
            //You can add custom options too. Also, it returns a promise for the user's response.
            app.showMessage('Search not yet implemented...');
        ,
        activate: function () 
            router.map([

                 route: '', title:'Page Title', moduleId: 'viewmodels/setup', nav: true ,
                 route: 'setup', moduleId: 'viewmodels/setup', nav: true ,
                 route: 'review', moduleId: 'viewmodels/review', nav: true 

            ]).buildNavigationModel();

            return router.activate();
        
    ;
);

JQuery 代码(60 秒计时器) 这是我试图插入 shell.js 以在页面上显示计时器的代码。

// TIMER: COUNTDOWN FROM 60 MINUTES WHEN PAGE IS LOADED

$(document).ready(function() 

  function countdown(element, minutes, seconds) 

    var time = minutes * 60 + seconds; // CREATE VARIABLE: SET TO 60 MINUTES (FOR ONE HOUR)
    var interval = setInterval(function() 

      var el = document.getElementById(element);

      $('#timer_ok, #timer_cancel, #dialog_overlay').on('click keypress', function() 
        $('#dialog').fadeOut(300);
        $('#dialog_overlay').fadeOut(300);
      );

      $(document).keyup(function(e) 

        // WHEN CLICKING "ESC" KEY CLOSE DIALOG WINDOW
        if (e.keyCode == 27) 
          $('#dialog').fadeOut(300);
          $('#dialog_overlay').fadeOut(300);
        
      );

      // WHEN CLICKED, RESET THE TIMER...
      $("#reset").on('click keypress', function() 
        time = 3600; // SET TIME TO 60 MINUTES
      );

      var minutes = Math.floor(time / 60);
      if (minutes < 10) minutes = "0" + minutes;

      var seconds = time % 60;
      if (seconds < 10) seconds = "0" + seconds;

      var text = minutes + ':' + seconds;
      el.innerhtml = text;
      time--;

    , 1000);
  

  countdown('countdown', 60, 00); // START THE TIMER INSIDE THE ELEMENT ('ID', MINUTES, SECONDS)

);

ma​​in.js 我们使用 RequireJS 来运行插件。添加这个以防有必要确定如何在 shell.js 文件中调用 JQuery。

requirejs.config(
    paths: 
        'text': '../vendor/require/text',
        'durandal':'../vendor/durandal/js',
        'plugins' : '../vendor/durandal/js/plugins',
        'transitions' : '../vendor/durandal/js/transitions',
        'knockout': '../vendor/knockout/knockout-3.4.0',
        'bootstrap': '../vendor/bootstrap/js/bootstrap',
        'jquery': '../vendor/jquery/jquery-1.9.1'
    ,
    shim: 
        'bootstrap': 
            deps: ['jquery'],
            exports: 'jQuery'
       
    
);

define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'bootstrap'],  function (system, app, viewLocator) 
    //>>excludeStart("build", true);
    system.debug(true);
    //>>excludeEnd("build");

    app.title = 'EV-CIS: Defects and Recalls Reporting';

    app.configurePlugins(
        router:true,
        dialog: true
    );

    app.start().then(function() 
        //Replace 'viewmodels' in the moduleId with 'views' to locate the view.
        //Look for partial views in a 'views' folder in the root.
        viewLocator.useConvention();

        //Show the app by setting the root view model for our application with a transition.
        app.setRoot('viewmodels/shell', 'entrance');
    );
);

请帮忙。

【问题讨论】:

我刚刚用你的倒计时方法创建了一个fiddle,它工作正常。检查控制台是否有任何错误。 另外,将clickkeyup 事件处理程序移到setInterval 之外。您正在添加事件处理程序 秒。一分钟后,document 将有 60 个keyup 事件处理程序! 感谢您帮助我在 JQuery 中设置计时器。但是,我遇到的问题是使用运行 Knockout JS 的 Durandal JS 框架运行 JQuery。它没有按照现有框架的设置方式运行任何 JQuery 代码。我会更新我的帖子。 Make VueJS and jQuery play nice的可能重复 你说定时器在 59:59 停止,所以我认为这有问题。您可以将countdown 函数添加到shell,而不是使用document.ready。然后在 shell 的 attached lifecycle event 中调用 functionattached函数在shell附加到DOM后触发。 【参考方案1】:

您可以使用compositionComplete Lifecycle Callback 添加您想要在 DOM 准备好后挂钩的所有 jquery 功能。

define(['plugins/router', 'durandal/app'], function (router, app) 
    return 
        router: router,
        search: function()  ,
        activate: function ()  ,
        compositionComplete: function()  
           // keep the click, keyup, keypress handlers here, outside setInterval
          var minutes = 60, seconds = 0;
          var time = minutes * 60 + seconds;

          var interval = setInterval(function () 

              var el = document.getElementById("countdown");

              var minutes = Math.floor(time / 60);
              if (minutes < 10) minutes = "0" + minutes;

              var seconds = time % 60;
              if (seconds < 10) seconds = "0" + seconds;

              var text = minutes + ':' + seconds;
              el.innerHTML = text;
              time--;

          , 1000);

        
    ;
);

Knockout 具有 keyupclick 绑定。因此,您也可以使用它们来代替 jquery 事件处理程序。

【讨论】:

成功了!将此添加到 shell.js 文件中,并且还能够运行多个 jquery 事件。谢谢!

以上是关于使用 Knockout 在 Durandal JS 框架中添加和运行 JQuery的主要内容,如果未能解决你的问题,请参考以下文章

Durandal:在一个孩子中创建功能并从另一个孩子中消费

使用 Durandal 的 compose 时 JQuery 不定位 DOM 元素

React Dynamic Table 未在 Knockout 项目中显示

Select2 Js 下拉菜单在 durandal Js 中不起作用

如果选择标题而不是值,则 Breeze/Knockout 下拉值不会在数据库中更新

淘汰赛验证:动态约束