【问题标题】:jQuery - Reinitialize DOM listenersjQuery - 重新初始化 DOM 监听器
【发布时间】:2016-12-11 02:57:22
【问题描述】:

我有很多 jQuery 事件侦听器,它们在文档完成加载时进行初始化。那部分工作正常。我有一个函数,它可以进行 ajax 调用并以 HTML 字符串的形式获取响应,这些 HTML 字符串使用 jQuery 附加到 DOM 的某些部分。虽然追加有效,但新的 HTML sn-p 代码不适用于 jQuery 事件侦听器,因为它在加载时不是 DOM 的一部分。有没有办法重新初始化 jQuery 事件监听器?

还有一件事:我尝试将事件侦听器存储在一个函数(函数a)中,并在我希望重新初始化侦听器时调用该函数。这部分奏效了……虽然监听器响应了新的 HTML sn-ps,但监听器的结果翻了一番,并且每当调用函数 a() 时都会加倍,从而导致一个重大错误。

我正在混合使用 jQuery 和 Angular。这是一个sn-p:

$(document).ready(function(){
     $('.like-btn').click(function(){

      var likeStatus = $(this).data('like-status-json');
      var contentType = $(this).data('content-type');
      var contentID = $(this).data('content-id');
      var likeMeter_id = '#' + contentType.toLowerCase() + '-' + 'likemeter' + '-' + contentID;
      var likeMeter_elm = $(likeMeter_id);

      // console.log( likeStatus, contentType, $(likeMeter_elm) );

      var obj = {
        likeStatus: likeStatus,
        contentType: contentType,
        contentID: contentID,
        likeMeter_elm: likeMeter_elm,
        likes: parseInt( $(likeMeter_elm).text() ),
        og_elm: $(this)
      }

      $scope.likeAction(obj);

    });
}); 

$scope.likeAction = function(dataObj) {
    // console.log(dataObj);

    var req = {
      method: 'POST',
      url: '/action/ajax/',
      headers: {
        'Content-Type': 'application/json',
        'responseType': 'json',
        "Accept" : "application/json",
        'X-CSRFToken': Cookies.get('csrftoken')
      },
      data: {
        action: dataObj.likeStatus.action,
        info: dataObj,
        csrfmiddlewaretoken: Cookies.get('csrftoken'),
      }
    }

    $http(req).then(function(resp){
      // Success Callback
      // console.log(resp);
      $(dataObj.og_elm).data('like-status-json', resp.data.likeStatus);
      $(dataObj.og_elm).removeClass(dataObj.likeStatus.class).addClass(resp.data.likeStatus.class);
      $(dataObj.og_elm).children('span.like-text').text(resp.data.likeStatus.text);
      $(dataObj.likeMeter_elm).text(resp.data.likeMeter);
    },
    function(resp){
      // Error Callback
      // console.log(resp);
    });
  }

这是附加新 HTML sn-ps 的 ajax:

$scope.addPostCommentUser = function(inputELM, dataObj) {
    if( inputELM == undefined || dataObj == undefined ) {
      console.log('Missing Inputs...');
      return;
    }

    console.log(dataObj);
    // return;

    var req = {
      method: 'POST',
      url: '/action/ajax/',
      headers: {
        'Content-Type': 'application/json',
        'responseType': 'json',
        "Accept" : "application/json",
        'X-CSRFToken': Cookies.get('csrftoken')
      },
      data: {
        action: 'addPostCommentUser',
        info: dataObj,
        csrfmiddlewaretoken: Cookies.get('csrftoken'),
      }
    }

    $http(req).then(function(resp){
      // Success Callback
      console.log(resp);
      var id = '#cmlst-' + dataObj.post_id;
      $(id).append(resp.data.comment_html)
      $(inputELM).val('');


    },
    function(resp){
      // Error Callback
      console.log(resp);
    });
  }

【问题讨论】:

    标签: javascript html jquery dom jquery-events


    【解决方案1】:

    您需要使用 on-call,而不是 click 和其他 - 这应该可以解决它。

    所以你可以用$('.like-btn').on('click',function()代替$('.like-btn').click(function()

    我不是 100% 确定它可以与你拥有的函数和 Angular 的混合使用,但试试看吧。

    【讨论】:

    • 所以它不起作用,但感谢您的尝试?事实证明,jQuery 侦听器只会侦听在读取/加载脚本时存在的元素。但是我确实找到了解决方法!
    • 我确定问题在于新的 HTML 没有绑定到 jQuery 选择器,因为它们在侦听器初始化时不存在。毫无疑问,选择元素的代码是正确的(它们是由 python jinja 模板引擎渲染的)。我通过创建一个将给定 DOM 元素绑定到 jQuery 侦听器的函数来修复/解决了这个问题。所以每当我从 AJAX 获取 HTML 作为字符串时,我都会创建一个新的 DOM 元素并将其传递给该函数。它工作得很好。
    【解决方案2】:

    使用事件委托将事件附加到动态创建元素的父元素。见.on()

    $("[id|=cmlst]")
    .on("click"
    , "css selector of element within `resp.data.comment_html` at `.then()`"
    , clickHandlerFunctionReference);
    

    【讨论】:

    • $(document).on('click', '.like-btn', function(){ /*...*/ })
    • 所以它不起作用,但感谢您的尝试?事实证明,jQuery 侦听器只会侦听在读取/加载脚本时存在的元素。但是我确实找到了解决方法!
    • @ryanwaite28 这个答案专门解决了这个问题。如果它对您不起作用,则说明您没有正确使用它。
    • @KevinB OP 在 Question/Answer 中使用不同的选择器,请参阅原始 Question 中的 var id = '#cmlst-' + dataObj.post_id; 和 OP 的 Answer 中的 var id = '#rplst-' + dataObj.comment_id;'#cmlst-' 不在 OP 的答案中。
    • 我的假设是 angular 正在破坏您将委托事件绑定到的父元素。我们必须更多地了解 angular 在页面中的附加和使用方式,才能知道我们可以使用哪个父级进行绑定(当然除了document
    【解决方案3】:

    我实际上找到了解决这个问题的方法。

    我创建了一个函数,该函数将 jQuery 事件侦听器应用于给定参数/输入参数的元素。因此,每当我从服务器端 AJAX 获取 HTML 字符串时,我都会使用 jQuery 创建一个新的 DOM 元素并将其传递给该函数! 实际上效果很好!!!

    示例如下:

    $scope.applyNewLikeListeners = function(elm) {
        $(elm).find('.like-btn').on('click', function(){
          var likeStatus = $(this).data('like-status-json');
          var contentType = $(this).data('content-type');
          var contentID = $(this).data('content-id');
          var likeMeter_id = '#' + contentType.toLowerCase() + '-' + 'likemeter' + '-' + contentID;
          var likeMeter_elm = $(likeMeter_id);
    
          var obj = {
            likeStatus: likeStatus,
            contentType: contentType,
            contentID: contentID,
            likeMeter_elm: likeMeter_elm,
            likes: parseInt( $(likeMeter_elm).text() ),
            og_elm: $(this)
          }
    
          $scope.likeAction(obj);
        });
      }
    

    有效!

    $scope.addCommentReplyUser = function(inputELM, dataObj) {
        if( inputELM == undefined || dataObj == undefined ) {
          console.log('Missing Inputs...');
          return;
        }
    
        console.log(dataObj);
        // return;
    
        var req = {
          method: 'POST',
          url: '/action/ajax/',
          headers: {
            'Content-Type': 'application/json',
            'responseType': 'json',
            "Accept" : "application/json",
            'X-CSRFToken': Cookies.get('csrftoken')
          },
          data: {
            action: 'addCommentReplyUser',
            info: dataObj,
            csrfmiddlewaretoken: Cookies.get('csrftoken'),
          }
        }
    
        $http(req).then(function(resp){
          // Success Callback
          console.log(resp);
          var id = '#rplst-' + dataObj.comment_id;
          var elm = $(resp.data.reply_html)
          $(id).append(elm)
          $(inputELM).val('');
          $(dataObj.replyMeter_elm).text(resp.data.replyMeter);
          $scope.applyNewLikeListeners(elm);
    
        },
        function(resp){
          // Error Callback
          console.log(resp);
        });
      }
    

    【讨论】:

      猜你喜欢
      • 2017-08-17
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多