【问题标题】:KnockoutJS: Tracking menu clicksKnockoutJS:跟踪菜单点击
【发布时间】:2011-07-14 13:14:43
【问题描述】:

我刚开始玩 KnockoutJS,它很吸引人。我成功创建了一些模板来呈现一个界面的两个面板,其中包含“ul”嵌套菜单。

这是我的模板:

<script id="menuItemTemplate" type="text/html">
    <li class='${ Class }' >
        <a class='${ Class }' data-bind='click: function() { viewModel.menuClicked(Id); }'>${ Name }</a>
        <ul class='${ Class }' data-bind='template: { name: "menuItemTemplate", foreach: Items }'></ul>
    <li>
</script>
<script id="menuTemplate" type="text/html">
    <ul class='${ Class }' data-bind='template: { name: "menuItemTemplate", foreach: Items }'></ul>
</script>
<script id="consoleTemplate" type="text/html">
    <div class='${ Class }' data-bind='template: { name: "menuTemplate", data: Menu }'></div>
</script>
<h2>Application Administration</h2>
<div id="console" class="console" data-bind='template: { name: "consoleTemplate", foreach: Panels }'>
</div>

这是我的视图模型的简化代码:

$(function () {
var viewModel = {
    "Panels": [
        {
        "Id" : 1,
        "Class": "main",
        "Menu": {
            "Id": 1,
            "Class": "file",
            "Name": "File",
            "Items": [{
                "Id": 1,
                "Class": "open",
                "Name": "Open",
                "Items": []
            }]
        }
    }]
};

    $.ajax({
        url: 'console.asmx/Initialize',
        type: "POST",
        cache: false,
        contentType: "application/json; charset=utf-8",
        data: "{}",
        dataType: "json",
        success: function (data) {
            viewModel = data.d;
            viewModel.menuActive = ko.observable(false);
            viewModel.currentMenu = ko.observable(0);
            viewModel.menuClicked = function (id) {
                viewModel.menuActive(true);
                viewModel.currentMenu(id);
            };
            ko.applyBindings(viewModel);
        }
    });
});

到目前为止,面板和菜单都渲染得很好,但我现在需要知道单击了哪个菜单并根据单击的菜单显示子菜单以及其他 UI 元素。我附加到超链接的函数抛出异常:'Uncaught ReferenceError: viewModel is not defined' 当我单击任何超链接时。

我还尝试将子菜单的可见性绑定到 viewModel 的“currentMenu”属性,但这破坏了一切:

<script id="menuItemTemplate" type="text/html">
    <li class='${ Class }' data-bind='visible: viewModel.menuActive && viewModel.currentMenu == Id'>
        <a class='${ Class }' data-bind='click: function() { viewModel.menuClicked(Id); }'>${ Name }</a>
        <ul class='${ Class }' data-bind='template: { name: "menuItemTemplate", foreach: Items }'></ul>
    <li>
</script>

如何正确绑定单击事件处理程序以及基于单击菜单的可见性?

【问题讨论】:

    标签: knockout.js jquery-templates


    【解决方案1】:

    您的问题是您的变量 viewModel 是在 jQuery 就绪函数中定义的,因此数据绑定中的函数看不到它,因为它不在全局范围内。甚至,在$(function() { ... }); 之外执行var viewModel = {} 也可以。

    您定义点击功能的方式对我来说看起来不错。不过,您的可见逻辑应该使用 viewModel.menuActive() 和 viewModel.currentMenu() 来访问表达式中的值。

    希望这会有所帮助。如果您遇到困难,我们很乐意提供进一步帮助。

    【讨论】:

    • 还有一个问题:目前我的可见逻辑仅通过检查currentMenu 属性来显示单击菜单的子项。我需要一种方法来显示单击的菜单所属的完整层次结构(父级、祖父级等)。有没有“淘汰”的方式来做到这一点?
    • 可能有几种方法可以解决这个问题。我可能会为每个项目添加一个dependentObservable,如果它是选定的菜单或者它的任何子项是选定的菜单,它将返回true。我想这对于任何较小的菜单集都会很好。如果性能是一个问题,那么您可能需要从子级引用父级,让 currentMenu 存储项目本身,然后单击时您可以先停用旧菜单,然后再激活新菜单。
    • 谢谢,非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    • 2013-06-29
    相关资源
    最近更新 更多