You need to enable JavaScript to run this app. jQuery的$(document).on('click')绑定动态元素在部分移动设备失效求助
优惠活动
大模型
产品
解决方案
定价
更多

jQuery的$(document).on('click')绑定动态元素在部分移动设备失效求助

问题场景

我写了一段脚本,因涉及动态生成元素所以使用.on()方法绑定点击事件,但该逻辑在部分移动设备、IE9环境下无法正常运行。


相关代码

restaurant.php 代码

<?php
($allow_order
    ? '<div class="add-menu">
            <div class="add-btn add-item-to-order">
                <span>' . $lang['ADD'] . '</span>
                <i class="icon-feather-plus"></i>
            </div>
' .
    (!empty($extras) ? '<span class="customize">' . $lang['CUSTOMIZABLE'] . '</span>' : '')
    . '        </div>'
    : '') .

theme.js 核心绑定代码

// add menu to order
$(document).on('click','.add-item-to-order', function (e) {
    e.preventDefault();

    var $add_customize = $('<div class="add-btn add-item-btn">' +
        '<div class="wrapper h-100">' +
        '<div class="addition menu-order-quantity-decrease">' +
        '<i class="icon-feather-minus"></i>' +
        '</div>' +
        '<div class="count">' +
        '<span class="num menu-order-quantity">1</span>' +
        '</div>' +
        '<div class="addition menu-order-quantity-increase">' +
        '<i class="icon-feather-plus"></i>' +
        '</div>' +
        '</div>' +
        '</div>'),
        $item = $(this).closest('.section-menu'),
        item_id = $item.data('id'),
        name = $item.data('name'),
        description = $item.data('description'),
        price = $item.data('price'),
        amount = $item.data('amount'),
        order_price = Number(amount),
        extras = TOTAL_MENUS[$item.data('id')].extras || [],
        order_data = JSON.parse(localStorage.getItem('quickqr_order')),
        random_id = randomId(10);


    $item.data('cart_id',random_id);
    if(extras.length == 0){
        order_data[random_id] = {
            'id': item_id,
            'item_name': name,
            'item_price': amount,
            'extras': {},
            'quantity': 1
        };

        localStorage.setItem('quickqr_order', JSON.stringify(order_data));

        $item.find('.add-menu').html($add_customize);
    } else {
        $menuCustomize.find('h4').html(name);
        $menuCustomize.find('.customize-item-description').html(description);
        $('#order-price').html(formatPrice(amount));
        $('#menu-order-quantity').text(1);

        var $extra_wrapper = $('#customize-extras');
        $extra_wrapper.html('');

        for (var i in extras) {
            if (extras.hasOwnProperty(i)) {
                var $extra_tpl = $(
                    '<div class="extras menu-extra-item">' +
                    '<span class="extra-item-title"></span>' +
                    '<div class="d-flex align-items-center">' +
                    '<span class="mr-2 extra-item-price"></span>' +
                    '<div class="custom-control custom-checkbox mr-sm-2">' +
                    '<input type="checkbox" class="custom-control-input" id="customControl">' +
                    '<label class="custom-control-label" for="customControl"></label>' +
                    '</div>' +
                    '</div>' +
                    '</div>');

                $extra_tpl.find('.custom-control-input').attr('id', 'checkbox' + extras[i].id);
                $extra_tpl.find('label').attr('for', 'checkbox' + extras[i].id);
                $extra_tpl.find('.extra-item-title').html(extras[i].title);
                $extra_tpl.find('.extra-item-price').html(formatPrice(extras[i].price));
                $extra_tpl.data('price', extras[i].price);
                $extra_tpl.data('id', extras[i].id);

                $extra_tpl.find('.custom-control-input').on('change',function () {
                    $('#menu-order-quantity').text(1);
                    calculateOrderPrice(amount);

                });
                $extra_wrapper.append($extra_tpl);
            }
        }

        $menuCustomize.find('.menu-order-quantity-decrease').off().on('click', function (e) {
            e.stopPropagation();
            var quatity = Number($('#menu-order-quantity').text()) - 1;
            if(quatity == 0){
                quatity = 1;
            }
            $('#menu-order-quantity').text(quatity);
            calculateOrderPrice(order_price);
        });
        $menuCustomize.find('.menu-order-quantity-increase').off().on('click', function (e) {
            e.stopPropagation();
            $('#menu-order-quantity').text(Number($('#menu-order-quantity').text()) + 1);
            calculateOrderPrice(order_price);
        });

        $('#add-order-button').off().on('click', function (e) {
            calculateOrderPrice(order_price);
            var price = $('#order-price').html();
            var order_data = JSON.parse(localStorage.getItem('quickqr_order'));

            // this order's extras
            var extras = {};
            $('.menu-extra-item').each(function () {
                if($(this).find('.custom-control-input').is(':checked')){
                    extras[randomId(10)] = {
                        'id': $(this).data('id'),
                        'name': $(this).find('.extra-item-title').html(),
                        'price': $(this).data('price')
                    };
                }
            });

            order_data[random_id] = {
                'id': item_id,
                'item_name': name,
                'item_price': amount,
                'extras': extras,
                'quantity': $('#menu-order-quantity').text()
            };

            localStorage.setItem('quickqr_order', JSON.stringify(order_data));

            $add_customize.find('.menu-order-quantity').text($('#menu-order-quantity').text());
            $item.find('.add-menu').html($add_customize);

            manageViewOrder();
            $('.overlay').trigger('click');
        });


        $menuCustomize.addClass('active');
        $('.overlay').addClass('active');
        $('body').addClass('noscroll');
    }
    manageViewOrder();
});

数量减少绑定代码

$order_tpl.find('.menu-order-quantity-decrease').off().on('click', function (e) {
    e.stopPropagation();
    var $item = $(this).closest('.section-menu');
    var $quantity = $item.find('.menu-order-quantity');
    var quantity = Number($quantity.text()) - 1;
    var cart_key = $item.data('cart_id');
    var $menu_item = $('.section-menu[data-id="' + order_data[cart_key]['id'] + '"]');
    if (quantity == 0) {
        var $add_btn = $('<div class="add-btn add-item-to-order">' +
            '<span>' + LANG_ADD + '</span>' +
            '<i class="icon-feather-plus"></i>' +
            '</div>');
        $menu_item.find('.add-menu').html($add_btn);
        delete order_data[cart_key];

    } else {
        $menu_item.find('.menu-order-quantity').text(quantity);
        order_data[cart_key]['quantity'] = quantity;
    }

    localStorage.setItem('quickqr_order', JSON.stringify(order_data));
    generateViewOrder();
});

问题排查及解决方案
  • 事件委托层级问题:旧版安卓和IE9下,将点击事件直接绑定到document上容易出现响应丢失、延迟的问题,建议把事件委托绑定到所有菜单的最近非动态父级容器(比如菜单列表外层固定的.menu-wrapper),不要直接绑定到document上。
  • 点击区域识别问题:旧移动设备触摸识别精度低,给.add-item-to-order设置最小宽高不低于48px,同时添加cursor: pointer属性,可以触发移动设备的点击事件识别逻辑。
  • 事件解绑冲突问题:代码中多次使用无参数的.off()解绑事件,会清除同元素上所有绑定的同类型事件,建议使用事件命名空间区分,比如解绑写.off('click.addOrder'),绑定写.on('click.addOrder'),避免误删其他逻辑的绑定事件。
  • localStorage解析异常问题:IE9下JSON.parse处理null值会直接报错,获取localStorage时补充默认值即可:order_data = JSON.parse(localStorage.getItem('quickqr_order') || '{}')。
  • 变量拼写错误问题:代码中出现quatity拼写错误(正确拼写为quantity),部分严格模式的JS引擎会抛出未定义变量错误,修正拼写即可解决。

内容的提问来源于stack exchange,提问作者zaxf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 14:45:00