JS: 将此函数更改为处理链接点击

3

以下是示例非常简单的jQuery和PHP Ajax请求 - 可以直接使用的代码

我已经成功创建了一个下拉列表,它将值传递给外部PHP脚本,并将HTML输出返回到同一页上的“div”中,它运行得很好。

现在我想要做的是在单击链接时发布值,而不是构建下拉列表。因此...如果我创建了这个链接:

<a href="foo.php?route_number=2">Route Number 2</a>

我希望将数字“2”传递给外部的PHP脚本,并更改“div”中的内容,就像下拉菜单目前所做的那样。我不知道如何更改JavaScript来处理这个问题,或者“foo.php”实际上需要什么。
以下是该示例的当前JavaScript代码:
    <script type="text/javascript">
    $(document).ready(function() {
        $('#route_number').click(function() {
            routenumber = $('#route_number').val();
            $.post('api.php', { route_number : routenumber }, function(res) {
                $("#mainlayer").html(res);
            });
         });
    });
    </script>

以下是HTML中下拉菜单部分的代码:

    <select name="route_number" id="route_number">
    <option value="notchosen">Please Choose A Route</option>
    <option value="2">Riverfront</option>
    <option value="11">Magazine</option>
    <option value="16">Claiborne</option>
    </select>
    <div id="mainlayer">

    </div>

为了明确,我想创建一些链接来实现传递值的下拉菜单所能实现的同样效果。

提前感谢您的帮助,

  • 丹 -
4个回答

2
创建一个类,捕获其值(指您单击的任何链接),然后发布。
<a class="RouteNumber" href="foo.php?route_number=2">Route Number 2</a>

$(function(){
    $('a.RouteNumber').on('click',function(event){
        // prevent the browser's default action for clicking on a link
        event.preventDefault();

        // break href attribute into array, then parse desired value as int
        var routenumber = $(this).attr('href').split('='),
            rtnum = parseInt(routenumber[1]);

        $.post('api.php',{route_number:rtnum},function(res){
            $("#mainlayer").html(res);
        });
    });
});

如果你不需要将整数解析出来(如果字符串足够好),那么你就不需要第二个变量。你可以在提交的数据中只使用routenumber [1]
提醒一下,我修改了jQuery以使用.on()语法。 .click()是它的简写,但我喜欢使用.on(),因为它允许在代码编写方面有更少的潜在问题,如果你想做更多的事情(例如mouseenter/mouseleave),因为你可以将它们组合成一个代码集。

谢谢您的帮助。当我尝试这个时,它试图重定向到我的“foo.php”页面进行处理。我不需要它去那里。在原始脚本中,它只是将“route_number”值传递给脚本,并仅接收处理后的输出,而无需离开页面。我做错了什么吗? - dan
我添加了一个缺失的 var 并插入了 event.preventDefault(); - 最后一个是必要的,以防止浏览器实际上“执行链接”。 - rodneyrehm
谢谢。我现在可以确定它正在“尝试”传递值,但是变量作为空字符串传递,因此查询不会执行。当我回显正在执行的查询时,保存“route_number”的变量从未接收到值(...并且route_number=$route_number...)...我需要做些其他的事情吗? 再次感谢您的帮助。 - dan
哦,我完全忘记了 e.preventDefault()。好吧,我也更新了代码以正确获取值。另一个答案使用了数据属性,这同样有效,但我选择了“将 href 拆分为数组”的方法。它会抓取括号后面的值,并将其解析为整数。 - PlantTheIdea

1
我本来希望只是简单地修复 @LifeInTheGrey 的示例就足够了,但我会做一些不同的事情,可能需要一些解释。
您的HTML可能看起来像这样:

<a class="route" href="foo.php?route_number=2" data-route="2">Route Number 2</a>

JavaScript代码大致如下:
$(function() {
    var fill_div_with_response = function(res) {
        $("#mainlayer").html(res);
    };

    var handle_error = function(res) {
        alert('something went wrong!');
    };

    $(document.body).on('click', '.route', function(event) {
        // prevent the browser's default action for clicking on a link
        event.preventDefault();
        // grab route number from data attribute
        var route = $(this).data('route');
        // make that post request
        $.post('api.php', {route_number: route})
            // handle the response
            .done(fill_div_with_response)
            // handle errors
            .fail(handle_error);
    });
});
  1. 该示例使用委托事件。它们初始化成本低,消耗的内存最少。
  2. 该示例处理错误。大多数类似问题的答案都忽略了这一点。错误总是会发生的。让人们意识到这一点。当然,抛出一个alert()并不是你想做的事情,但它仍然比完全忽略错误要好。
  3. 该示例使用延迟对象(Promises)而不是回调函数,因为这通常使代码更加清晰。
  4. 我们在根闭包中定义回调函数fill_div_with_response()handle_error(),以防止在下一次点击时重新定义它们。没有必要喂垃圾收集器。
  5. 数据属性是<option value="123">的最佳替代方案,因为它避免了您必须解析href属性以从字符串中提取该数字。

Rodney:这也非常好用。感谢您详细解释了其优点、利弊! - dan

1

由于您想制作菜单,我会修改您的标记

<ul name="route_number" id="route_number">
    <li value="2">Riverfront</li>
    <li value="11">Magazine</li>
    <li value="16">Claiborne</li>
</ul>

然后简单地处理该列表:
$('#route_number').find('li').click(function () {
    var routenumber = $(this).attr('value');
    $.post('api.php', {
        route_number: routenumber
    }, function (res) {
        $("#mainlayer").html(res);
    });
});

编辑1:作为一种改进(因为您似乎对这方面还很新),您可以使用更改后的标记数据,如下所示:

<ul name="route_number" id="route_number">
    <li data-routenumber="2">Riverfront</li>
    <li data-routenumber="11">Magazine</li>
    <li data-routenumber="16">Claiborne</li>
</ul>

那么代码应该是这样的:

$('#route_number').find('li').click(function () {// add click event manager to each li
    var routenumber = $(this).data('routenumber');// get routenumber of clicked
    $.post('api.php', {
        route_number: routenumber
    }, function (res) {
        $("#mainlayer").html(res);
    });
});

使用 .on() 形式的备用代码

$('#route_number').on('click, 'li', function () {//click event manager for ul/li
    var routenumber = $(this).data('routenumber');// get routenumber of clicked
    $.post('api.php', {
        route_number: routenumber
    }, function (res) {
        $("#mainlayer").html(res);
    });
});

请注意,这种最后的形式绑定到#route_number元素,因此您可以在处理过程中添加更多的菜单选项,它们仍然可以正常工作。这也比附加到文档更好,因为它是一种更专注于事件附加的方法。

每个“li”中的值如何传递到我的api.php页面?谢谢 :) - dan
var routenumber = $(this).attr('value'); 从被点击的 li 元素中提取 value 属性,然后将其传递到 $post 的 route_number 中 - 我觉得这部分代码很明显... 可能不是吧。 - Mark Schultheiss
我添加了一个新的表单,使用元素中的数据,这可能比属性更强大,并且更标准化。此外,我展示了使用.on()方法的形式,这可能有助于您提供另一种适用于动态创建元素的选项。 - Mark Schultheiss
好的,谢谢Mark。我也会去看看这个。 - dan

0

我理解你的问题是,你的功能已经很好了,你只需要将下拉框中的选项更改为文本。如果是这样,那太好了!你可以保留(几乎)相同的JavaScript代码。

现在,你的JavaScript代码正在获取选择框的值,通过AJAX发送它,并使用返回的值。你唯一需要更改的是获取所点击文本的“value”。

你不想使用链接,因为它是设计用来带用户去某个地方的。相反,你可以使用一个span标签,并将其格式化成链接的外观,甚至是按钮的外观,如果你想要这种外观的话。

你还需要更改$('#route_number').val();,可能改为通过点击事件传递的某些内容。例如:

<span id="route1" class="routeSpan" onclick="sendVal(1)">Route 1 Name</span>
<span id="route2" class="routeSpan" onclick="sendVal(2)">Route 2 Name</span>

还有你的JavaScript代码:

function sendVal(routeVal) {
    $.post('api.php',{route_number:routeVal},function(res){
    $("#mainlayer").html(res);
    });
}

1
请不要建议使用内联事件处理程序,例如 onclick="sendVal(1)"。请参考 @LifeInTheGrey 的答案进行适当的事件绑定。 - rodneyrehm
这个很好用。关于这个有一个问题。如果我想在菜单中使用这个“span”的方法,是否有任何预见的问题?最终,这些链接/跨度将成为菜单的一部分。我假设将这些跨度包括在“div”中作为CSS菜单的一部分,应该都没问题吧? 感谢您的帮助!-丹 - dan
罗德,你能详细解释一下它们之间的区别吗? - dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接