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

Posted

技术标签:

【中文标题】使用 Durandal 的 compose 时 JQuery 不定位 DOM 元素【英文标题】:JQuery doesn't locate DOM elements when using Durandal's compose 【发布时间】:2013-09-13 02:51:11 【问题描述】:

我最近使用 Knockout 和 JQuery 将我公司的项目移植到了 Durandal。直截了当地说:我需要使用两个 html 输入来初始化 JQuery UI 的日期选择器。但是,当我这样做时,JQuery 无法找到输入:

查看:

<div data-bind="if: !CurrentUser()">
    <h1 data-bind="html: DisplayName"></h1>

    <div data-bind="compose: 'users/_UsersList.html'"></div>
</div>

<div data-bind="with: CurrentUser(), visible: CurrentUser()">
    <h1>User detail</h1>

    <div data-bind="compose: 'users/_UserDetail.html'"></div>
</div>

viewmodel - 在第一个 div 中选择用户时调用 SelectUser() 函数,然后加载第二个 div 和 users/_UserDetail.html:

users.SelectUser = function (user) 
    users.CurrentUser(user);

    /* ... */

    $(function () 
        $("#datepickerFrom").datetimepicker(
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss",
            defaultDate: null
        );

        $("#datepickerTo").datetimepicker(
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss"
        );
    );

_UserDetail.html 的重要部分

<div class="control-group">
    <label class="control-label">Active from</label>
    <div class="controls">
        <input type="text" data-bind="value: ActiveFrom" id="datepickerFrom" />
    </div>
</div>
<div class="control-group">
    <label class="control-label">Active to</label>
    <div class="controls">
        <input type="text" data-bind="value: ActiveTo" id="datepickerTo" />
    </div>
</div>

然后两个 HTML 输入未定义。如果我将 divcompose 绑定更改为实际的 users/_UserDetail.html 内容,它工作得很好,但是视图很快就会变得一团糟——html文件并不小。如果有人能指出我正确的方向,我将不胜感激。谢谢!

【问题讨论】:

您应该创建一个自定义绑定处理程序并在您的视图中使用它。另请阅读有关 DOM 操作的 durandal 文档:durandaljs.com/documentation/Interacting-with-the-DOM 在调用加载视图的代码吗?还是由框架处理? 您是指compose: 代码吗?由框架调用,但在触发SelectUser() 时会触发 - 当我从 users/_UsersList.html 中选择用户时调用此函数。 【参考方案1】:

在这种情况下,您需要一个敲除绑定处理程序。

在某些情况下,绑定处理程序可能会遇到组合生命周期问题,如果是这种情况并且您使用的是 Durandal 2,则可以使用方法 composition.addBindingHandler。否则只需使用ko.bindingHandlers

您需要在shell.jsmain.js 中创建绑定,以便它们在所有应用程序中都可用。使用以下代码:

 var composition = require('durandal/composition');
 composition.addBindingHandler('datetimepicker', 
            init: function (element, valueAccessor) 
                var activeTo =  valueAccessor();  //What do you want to do with this value?
                $(element).datetimepicker(
                   dateFormat: "d. m. yy",
                   timeFormat: "HH:mm:ss",
                   defaultDate: null   //Maybe use activeTo here?
                  );
            
         );

在您的用户界面中:

 <input type="text" data-bind="datetimepicker: ActiveTo" id="datepickerTo" />

注意:

此代码可能不起作用,但您绝对应该使用这种方法来创建此类控件并使用 Durandal 的组合生命周期。

【讨论】:

完美运行。感谢,并有一个愉快的一天! :)【参考方案2】:

很确定问题出在这个:

users.SelectUser = function (user) 
    servers.CurrentUser(user);

    /* ... */

    $(function () 
        $("#datepickerFrom").datetimepicker(
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss",
            defaultDate: null
        );

        $("#datepickerTo").datetimepicker(
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss"
        );
    );

您的 jQuery datepicker 初始化代码位于一个函数中。这意味着它只会在SelectUser 函数被调用时运行。尝试将其移到任何函数之外。

【讨论】:

感谢您的回答,但是当 SelectUser 函数被触发时,_users/UserDetail.html 和两个输入被加载 - 这两个 DOM 元素直到那时才存在。 好吧,那么使用$()$(document).ready() 并不是正确的方法,因为视图是通过AJAX 加载的,所以ready 事件已经触发了。 你建议我应该用什么来代替 $()? 你需要弄清楚你是否可以挂钩到 durandal 的组合机制。大多数框架都会公开一个在内容被加载/添加到 DOM 时触发的事件。 那是您要设置日期选择器的地方。 好的,我会再次尝试通读他们的文档,因为我知道我需要查找什么。 :) 谢谢。

以上是关于使用 Durandal 的 compose 时 JQuery 不定位 DOM 元素的主要内容,如果未能解决你的问题,请参考以下文章

你可以通过 Durandal activationData compose 绑定传递多个参数吗?

将 compose 数据绑定与另一个数据绑定一起使用

Durandal js,所有功能在启动时激活

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

Durandal JS 淘汰赛延期更新

如何使用requirejs构建durandal应用程序?