1

我正在尝试用widget面向对象的 JavaScript 编写 JavaScript,或者至少是我理解的 JS 几乎等效的类。

我想要实现的只是一个改变状态的菜单。在伪;

  • 加载小部件后,#nav使用包含year group<ul>的菜单填充。 <li>
  • 单击一年组后,将其<li>清空并用该年的导师组重新填充它,并附加一个链接。#nav ul<li> <li>return
  • 单击return链接后,清空并使用原始年份组#nav菜单重新填充它,同时能够利用上述所有功能。 <ul>

从历史上看,即迄今为止,我使用“嵌入式”函数来尝试将所有内容保持在同一个 DOM 层/时序内。我真的不明白其中任何一个是如何工作的,或者这是否是一件合适的事情,但代码本身似乎工作。

这是我以前完成的方式的一个示例:

var GroupsDisplayHTML = '<h2>Tutor Groups</h2>' +
    '<ul><li><a class="year" href="javascript:void(0);" title="Year 9" id="9">Year 9</a></li>' +
    '<li><a class="year" href="javascript:void(0);" title="Year 10" id="10">Year 10</a></li>' +
    '<li><a class="year" href="javascript:void(0);" title="Year 11" id="11">Year 11</a></li>' +
    '<li><a class="year" href="javascript:void(0);" title="Year 12" id="12">Year 12</a></li>' +
    '<li><a class="year" href="javascript:void(0);" title="Year 13" id="13">Year 13</a></li></ul>';

$("div#groups").html(GroupsDisplayHTML);

$('a.year').click( function() {
    var Groups;
    var Groups_Sorted = [];

    Frog.API.get('groups.getAll',
    {
        'onSuccess': function (data) { Groups = data; },
        'onError': function(err) { alert(err); }
    });

    for (var i = 0; i < Groups.length; i++) {
        var Year = $(this).attr("id");

        if (Groups[i].name.indexOf(Year) == 0 && Groups[i].name.indexOf('/Tp') != -1) {
            var arrayToPush = { 'id': Groups[i].id, 'name': Groups[i].name };
            Groups_Sorted.push(arrayToPush);
        }
    }

    GroupsDisplayHTML = '<h2>Year ' + Year + '</h2><ul>';

    for(var i = 0; i < Groups_Sorted.length; i++){
        GroupsDisplayHTML += '<li><a class="group" href="javascript:void(0);" title="' + Groups_Sorted[i].id + '" id="' + Groups_Sorted[i].id + '">' + 
            Groups_Sorted[i].name + ' <span style="font-size:10px;color:#bbb;">(' + Groups_Sorted[i].name + ')</span></a></li>';
    }

    GroupsDisplayHTML += '<li><a class="return" href="javascript:void(0);">&lt;- Back to Year Groups</a></li></ul>';

    $("div#groups").html(GroupsDisplayHTML);

    $('a.group').click( function() {
        var Group_ID = $(this).attr("id");
        AssignPoints.getUsers(Group_ID);
    });

    $('a.return').click( function() {
        AssignPoints.displayGroups(data);
    });
});

但是,现在,我想知道是否更好的方法是使用 jQuery 的on函数。这是我目前正在编写的代码(*只是为了尝试实现更改状态菜单):

var TutorGroupPoints = {
    URL: 'http://staff.curriculum.local/frog/rewards.php',
    currentUser: UWA.Environment.user.id,
    groupsObject: { },
    sortedArray: [ ],
    navHTML: '<h2>Tutor Groups</h2>' +
        '<ul>' +
            '<li><a class="year" title="Year 9" id="9">Year 9</a></li>' +
            '<li><a class="year" title="Year 10" id="10">Year 10</a></li>' +
            '<li><a class="year" title="Year 11" id="11">Year 11</a></li>' +
            '<li><a class="year" title="Year 12" id="12">Year 12</a></li>' +
            '<li><a class="year" title="Year 13" id="13">Year 13</a></li>' +
        '</ul>',

    init: function() {
        /* caching outer this -> AJAX scope problems */
        var that = this;

        /* retrieve all of the user groups from Frog VLE and store them in an object-level variable */
        Frog.API.get('groups.getAll',
        {
            'onSuccess': function (data) { that.groupsObject = data; },
            'onError': function(err) { alert(err); }
        });

        /* populate the div#nav with our year group UL */
        $('#nav').append(this.navHTML);

        /* using "on" because the LIs have been created in the DOM? */
        $('#nav ul').on("click", "li a", function(e) {
            e.preventDefault();
            that.yearClick( $(this).attr("id") );
        });
    },

    yearClick: function(year) {
        /* run through groupsObject and pull out any tutor groups found in the year we've clicked on
           then put those into our sortedArray */
        for (var i = 0; i < this.groupsObject.length; i++) {
            if (this.groupsObject[i].name.indexOf(year) == 0 && this.groupsObject[i].name.indexOf('/Tp') != -1) {
                /* all we need is name and id */
                var arrayToPush = { 'id': this.groupsObject[i].id, 'name': this.groupsObject[i].name };
                this.sortedArray.push(arrayToPush);
            }
        }

        /* clear the existing UL from div#nav */
        $('#nav ul').empty();

        /* populate div#nav's UL with LIs of our tutor groups (label being name, attr="id" being id) and
           clickable links for each */
        for (var i = 0; i < this.sortedArray.length; i++) {
            $('#nav ul').append('<li><a class="tutor" id="' + this.sortedArray[i].id + '">' + this.sortedArray[i].name + '</a></li>');
        }

        /* add a "return" link to view other years' tutor groups */
        $('#nav ul').append('<li><a id="return">&lt;- Return</a></li>');

        /* upon clicking the return link, empty #nav ul then re-append our navHTML from earlier */
        $('#nav ul').on("click", "a#return", function(e) {
            e.preventDefault();
            $('#nav ul').empty();
            $('#nav').append(this.navHTML);
        });

        /* upon clicking any of our tutor group LIs, display that link's id so that we can use it in
           another function to actually display some content */
        $('#nav ul').on("click", "a.tutor", function(e) {
            e.preventDefault();
            alert( $(this).attr("id") );
        });
    }

};

widget.onLoad = function(){
    /* run our "class" */
    TutorGroupPoints.init();
}

和 HTML:

<div id="wrapper">
    <div id="nav">

    </div>
    <div id="content">

    </div>
</div>

我在这里创建了一个 jsFiddle,这是对代码的轻微操作(即我已经删除了无法访问的 Frog API 调用并用固定对象替换它们)。希望这能充分发挥作用。

这里的问题是,一旦我点击返回按钮,什么都没有发生。此外,我怀疑修复返回按钮会为我提供一些链接,当点击这些链接时,它们什么也不做。

理想情况下,根据代码的底部,当用户单击特定的导师组时,我想在我的 TutorGroupPoints 类中运行另一个函数。这将如何影响我的返回按钮等?他们会因为没有从“当前”功能运行而停止工作吗?

不仅仅是“只是”对我的代码问题的回答,我更想要一些方向,即我最近编写的代码是否比旧代码更好?我应该使用on还是应该使用嵌入式 jQuery 函数和通信类函数?

提前致谢,

4

1 回答 1

1

简短回答:http: //jsfiddle.net/byzgv/4/

我不确定 OOP 方面,但这似乎是您的情况:

  1. 加载页面时,将列表插入到 div 中。
  2. 您将一些事件处理程序添加到此列表中
  3. 您单击一个列表项,您的事件处理程序运行,并更改列表项。
  4. 单击“返回”列表项“什么都不做”。

在您的小提琴中,单击“返回”列表项确实会执行某些操作,它会清空此列表。这部分是你要求它做的:

$('#nav').on("click", "ul a#return", function(e) {
    e.preventDefault();
    $('#nav ul').empty();
    $('#nav').append(this.navHTML);
});

所以这个事件处理程序已经触发,前两条指令已经生效。调用append不起作用,因为您处于不同的上下文中 -this不引用 TutorGroupPoints 对象。因此,您可以通过明确引用您的对象来解决此问题:

$('#nav').on("click", "ul a#return", function(e) {
    e.preventDefault();
    $('#nav ul').empty();
    $('#nav').append(TutorGroupPoints.navHTML);
});

(顺便说一句,您正在附加一个全新的列表,所以您需要这样做$('#nav').empty();而不是$('#nav ul').empty();

然后,如您所料,单击“返回”项会为您提供一个不响应单击事件的新列表。这是因为您调用该on函数的方式。在设置事件处理程序时,您调用的 jQuery 对象on必须存在。在您的init函数中,当您设置事件处理程序时,该列表确实存在,因为您将其附加到div调用之前on。但后来,你丢弃了这个列表并替换它。

要让您的事件处理程序处理所有列表而不仅仅是第一个列表,您需要将事件处理程序附加到从一开始就存在且不会更改的元素,即#navdiv。所以

$('#nav ul').on("click", "li a", function(e) {

可以变成

$('#nav').on("click", "ul li a", function(e) {
于 2012-08-15T10:27:01.177 回答