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
相关产品推荐
相关产品推荐

