jQuery on()方法绑定动态元素的点击事件


我正在做一个商城相关的项目,需要用到购物车。购物车的数据我存在了session里,但是在前端需要实时更新购物车的数据,所以动态的创建了元素。
在jquery中,要给动态元素绑定事件,我使用了on方法,但是该方法一直不生效,必须刷新页面才能删除购物车的数据,请大家帮忙看看。
项目使用的是ThinkPHP框架。


 <?php
/**
 * 
 * @authors tudouya (http://www.php101.cn/)
 * @date    2015-04-08 01:37:39
 * @version $1.0$
 */
namespace Mall\Controller;
use Think\Controller;

class CartController extends Controller {
    public function __construct(){
        parent::__construct();

        // session(null);
        if(!isset($_SESSION['cart'])){
            $_SESSION['cart'] = array();
        }
    }

    public function index(){
        kd($_SESSION);
    }

    public  function addItem(){
        /*
         * TODO --- 安全方面的考虑
         */
        $good_id = intval(I('post.good_id'));

        if(isset($_SESSION['cart'][$good_id])){
            $_SESSION['cart'][$good_id]['good_num'] += 1;
            $html = '';
            $total_price = 0;
            foreach($_SESSION['cart'] as $k=>$v){
                $total_price += $v['good_price']*$v['good_num'];
                $html .= '<div class="shoppingCartProductWrapper"> <a  href="' . U('mall/index/gooddetail',array('id'=>$v['good_id'])) . '" class="shoppingCartProductImageWrapper">'.'<img src="'.$v['good_image'].'" class="shoppingCartProductImage" alt=""/></a><div class="shoppingCartProductInfoWrapper"> <a href="'.U('mall/index/gooddetail',array('id'=>$v['good_id'])).'" class="shoppingCartProductTitle">'.$v['good_name'].'</a><div class="shoppingCartProductButtonsWrapper"><input type="text" id="shoppingCartProductNumber-1" class="shoppingCartProductNumber" name="product-1" value="'.$v['good_num'].'" /><span class="shoppingCartProductPrice">'.$v['good_price'].'</span><a href="javascript:void(0)" class="shoppingCartRemoveProductButton"></a> </div></div></div>';
            }
            $html .= '<div class="shoppingCartInfoWrapper"><span class="shoppingCartProductsNumber">商品数量:'.count($_SESSION['cart']) . '</span><span class="shoppingCartProductsTotal">Total: ¥'.$total_price.'</span></div>';
            exit($html);
        }
        $good_name = I('post.good_name');
        $good_price = I('post.good_price');        
        $good_image = I('post.good_image');
        $good_num = intval(I('post.good_num'));
        $good = compact('good_id', 'good_name', 'good_price', 'good_image', 'good_num');
        $_SESSION['cart'][$good_id] = $good;

        $html = '';
        $total_price = 0;
        foreach($_SESSION['cart'] as $k=>$v){
            $total_price += $v['good_price']*$v['good_num'];
            $html .= '<div class="shoppingCartProductWrapper"> <a  href="' . U('mall/index/gooddetail',array('id'=>$v['good_id'])) . '" class="shoppingCartProductImageWrapper">'.'<img src="'.$v['good_image'].'" class="shoppingCartProductImage" alt=""/></a><div class="shoppingCartProductInfoWrapper"> <a href="'.U('mall/index/gooddetail',array('id'=>$v['good_id'])).'" class="shoppingCartProductTitle">'.$v['good_name'].'</a><div class="shoppingCartProductButtonsWrapper"><input type="text" id="shoppingCartProductNumber-1" class="shoppingCartProductNumber" name="product-1" value="'.$v['good_num'].'" /><span class="shoppingCartProductPrice">'.$v['good_price'].'</span><a href="javascript:void(0)" class="shoppingCartRemoveProductButton"></a> </div></div></div>';
        }
        $html .= '<div class="shoppingCartInfoWrapper"><span class="shoppingCartProductsNumber">商品数量:'.count($_SESSION['cart']) . '</span><span class="shoppingCartProductsTotal">Total: ¥'.$total_price.'</span></div>';

        exit($html);
    }

    public function removeItem(){
        $good_id = intval(I('post.good_id'));
        unset($_SESSION['cart'][$good_id]);

        $html = '';
        $total_price = 0;
        foreach($_SESSION['cart'] as $k=>$v){
            $total_price += $v['good_price']*$v['good_num'];
            $html .= '<div class="shoppingCartProductWrapper"> <a  href="' . U('mall/index/gooddetail',array('id'=>$v['good_id'])) . '" class="shoppingCartProductImageWrapper">'.'<img src="'.$v['good_image'].'" class="shoppingCartProductImage" alt=""/></a><div class="shoppingCartProductInfoWrapper"> <a href="'.U('mall/index/gooddetail',array('id'=>$v['good_id'])).'" class="shoppingCartProductTitle">'.$v['good_name'].'</a><div class="shoppingCartProductButtonsWrapper"><input type="text" id="shoppingCartProductNumber-1" class="shoppingCartProductNumber" name="product-1" value="'.$v['good_num'].'" /><span class="shoppingCartProductPrice">'.$v['good_price'].'</span><a href="javascript:void(0)" class="shoppingCartRemoveProductButton"></a> </div></div></div>';
        }
        $html .= '<div class="shoppingCartInfoWrapper"><span class="shoppingCartProductsNumber">商品数量:'.count($_SESSION['cart']) . '</span><span class="shoppingCartProductsTotal">Total: ¥'.$total_price.'</span></div>';
        exit($html);
    }
}
?>


 <!-- shopping cart wrapper start -->
    <form id="shoppingCartWrapper" class="shoppingCartWrapper" action="#" method="post">
      <fieldset>        
        <?php 
          $total_price = 0;
          foreach($_SESSION['cart'] as $k=>$v){
            $total_price += $v['good_price']*intval($v['good_num']);
        ?>
        <!-- shopping cart product starts -->
        <div class="shoppingCartProductWrapper"> 
          <a href="<?php echo DOMAIN.'/mall/index/gooddetail/id/'.$v['good_id'].'.html'; ?>" class="shoppingCartProductImageWrapper">
            <img src="<?php echo $v['good_image']; ?>" class="shoppingCartProductImage" alt=""/>
          </a>
          <div class="shoppingCartProductInfoWrapper"> 
            <a href="<?php echo DOMAIN.'/mall/index/gooddetail/id/'.$v['good_id'].'.html'; ?>" class="shoppingCartProductTitle"><?php echo $v['good_name']; ?></a>
            <div class="shoppingCartProductButtonsWrapper">
              <input type="text" class="shoppingCartProductNumber" name="product-3" value="<?php echo $v['good_num']; ?>"/>
              <input type="hidden" name="good_id" value="<?php echo $v['good_id']; ?>" />
              <span class="shoppingCartProductPrice">¥<?php echo $v['good_price']; ?></span><a href="javascript:void(0)" class="shoppingCartRemoveProductButton"></a> </div>
          </div>
        </div>
        <!-- shopping cart product ends --> 
        <?php } ?>

        <!-- shopping cart info wrapper starts -->
        <div class="shoppingCartInfoWrapper"> 
          <span class="shoppingCartProductsNumber">商品数量: <?php echo count($_SESSION['cart']); ?></span> 
          <span class="shoppingCartProductsTotal">Total: ¥<?php echo $total_price; ?></span> 
        </div>
        <!-- shopping cart info wrapper ends -->

        <div id="shoppingCartButtons" class="shoppingCartButtonsWrapper"><a href="" class="shoppingCartEmptyButton">清空</a>
          <input type="submit" value="去付款" id="shoppingCartCheckoutButton" class="shoppingCartCheckoutButton"/>
        </div>
      </fieldset>
    </form>
    <!-- shopping cart wrapper ends --> 
    <script type="text/javascript">
        $(function(){
          remove_url = "{:U('mall/cart/removeitem')}";
          $('#shoppingCartWrapper').find('.shoppingCartRemoveProductButton').on('click',function(){
            good_id = $(this).prev().prev().val();
            $.ajax({
              'url': remove_url,
              'type': 'post',
              'data': {'good_id': good_id},
              'success': function(data){
                    $('#shoppingCartButtons').prevAll().remove();
                    $('#shoppingCartButtons').before(data);
              }
            });
          });
        });
    </script>

线上演示地址:
http://weixin.chenfw.me/mall/index

jquery 事件绑定 动态元素

注册你妹啊! 9 years, 11 months ago

使用live,on只能绑定页面载入时已有的DOM对象。

乱入菌可好? answered 9 years, 11 months ago

请百度 事件委托 事件代理

不知火一树 answered 9 years, 11 months ago

.on(events, callback) 只能绑定页面已有元素的事件。
.on(events, selector, callback) 则是在 已有的元素 上绑定 代理的 事件处理器 ( addEventListener 实际上在该已有元素上调用),但只有事件的实际 source 是其子代元素并且符合 selector 时, callback 才会以该实际 source this 指向的对象被调用。

For example:


 $(document).on("click", "a", function () {
    console.log(this.tagName.toLowerCase()); // "a"
    return false;
});

这样即可监听页面创建时尚未存在的 <a> 元素所产生的事件。

http://api.jquery.com/on/

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.

In addition to their ability to handle events on descendant elements not yet created, another advantage of delegated events is their potential for much lower overhead when many elements must be monitored.

渣翻译:

委托事件 的优势是可以处理在其后添加入文档的子代元素所产生的事件。通过选择一个添加委托事件时必然存在的元素,你可以使用委托事件以避免频繁添加和移除事件处理器的需求。例如,该元素可以是在 MVC 设计中视图的包含元素,或者如果事件处理器要监控文档中所有冒泡的事件时,则是 document . document 在载入任何其它 HTML 之前即可在文档的头部获得,所以在此添加事件处理器而不用等待 document ready 是安全的。

除了处理尚未创建的子代元素上产生的事件,委托事件的另一个优势是需要监控多个元素时的性能更好。

艾露雅伊芙 answered 9 years, 11 months ago

对于动态绑定元素可以这样写


 $(document).on('click', '.xxx', function() {
   // do something
});

$(document)可以改成要绑定事件元素的父节点

.xxx 就是指的当前元素

这样就可以实现事件的代理

天朝可丽饼 answered 9 years, 11 months ago

Your Answer