【发布时间】:2020-11-20 12:30:06
【问题描述】:
我有一个购物车清单。 每个购物车都包含一个产品列表。
{# templates\Cart\list.twig #}
{% use 'Cart/details.twig' %}
{% extends '@templates/_base.twig' %}
{% block body %}
<div class="list-group" id="cart-list" role="tablist">
{% for cart in cart_list %}
<a class="products-list-cart list-group-item list-group-item-action {% if userCart.current %}active{% endif %}"
id="item-details-cart-{{ cart.id }}"
href="#products-list-cart-{{ cart.id }}"
data-href="{{ path('cart_product_list', {'cart_id':cart.id}) }}"
data-toggle="list" role="tab" aria-controls="products-list-cart-{{ cart.id }}"
{% if not first_cart %}data-product-list-loaded="true" {% set first_cart = true %}{% endif %}>
See cart details for cart {{ cart.id }}
{#
On click, make an ajax call to filled
in product list '#products-list-cart-{{ cart.id }}'
#}
</a>
{% endfor %}
</div>
<div class="tab-content" id="carts-content">
{% for cart in cart_list %}
{% set userCart = cart.userCart %}
<div class="tab-pane fade {% if userCart.current %}show active{% endif %}"
id="products-list-cart-{{ cart.id }}"
role="tabpanel"
aria-labelledby="cart-{{ cart.id }}">
{% if not first_cart_product_list %}
{% block cart_details %}
{{ parent() }}
{% endblock %}
{% else %}
<i class="fa fa-cog fa-spin fa-1x fa-fw"> </i> {{ "loading_product"|trans }}
... {#
Filled in on click on '.products-list-cart'.
Proceed to ajax call.
#}
{% endif %}
</div>
{% endfor %}
</div>
{% endblock %}
{% endblock %}
{% block javascripts %}
{{ parent() }}
{{ encore_entry_script_tags('cart') }}
{{ encore_entry_script_tags('product') }}
{% endblock %}
我尽量保持简单,我使用list tab bootstrap component。
当我必须包含入口点时,问题就来了。
因为我的 javascript 将事件侦听器添加到产品详细信息。
因此,第一个购物车的所有产品详细信息都可以正常工作,因为它们是在页面加载时加载的。
此行为由first_cart_product_list 变量管理。
当用户单击购物车查看其详细信息时,将显示所有其他产品列表。 问题是包含 javascript 的入口点仅将事件添加到使用 dom 加载的元素。
我尝试将入口点添加到我的Cart/details.twig 模板,但它会在每次 ajax 调用时加载。
所以这里的问题是所有 ajax 调用都将事件侦听器添加到所有现有的 $('a.products-list-cart') 元素。所以页面上的很多元素都有越来越多的事件监听器而不是一个。
我举个例子:
如果我将encore_entry_script_tags 添加到购物车详细信息模板:
{# Cart/details.twig #}
{{ encore_entry_script_tags('product') }}
它被添加到每个产品列表中,因此: 如果我有 4 辆购物车:
然后我单击每个以加载产品列表,该列表在页面上的每个产品上添加一个事件侦听器。 所以对于第一个购物车,我将在每个产品元素上设置 4 个事件监听器。
结果是当我点击第一个购物车的“添加到购物车”按钮时:
有 4 次调用 ajax 函数将产品数量更新到购物车中。
// product.js entry point...
$(document).ready(
function () {
$('.btn-add-product-to-cart').on( // This event listener is added to every button on product list
'click',
function (e) {
e.preventDefault();
$.ajax({
method: 'POST',
url: $(this).data('href'),# Call controller route to modify product quantity in DB
...
我尝试使用.one() 函数,因为我希望在每个元素上只添加一个事件侦听器。但不幸的是它不起作用。
任何帮助将不胜感激。
【问题讨论】:
-
“问题在于,包含 javascript 的入口点仅向使用 dom 加载的元素添加事件。” - 以及解决这个众所周知的问题的正确方法问题,称为事件委托。
-
我不知道事件委托,我来看看。感谢您为我指明正确的方向
标签: javascript jquery webpack