Jquery .click() 函数选择器问题



我目前正在构建一个PHP网页,该网页从SQL服务器检索数据并将检索到的数据输出为表。每个<tr>都有自己的类,如下所示:

"<table class='preview'>
      <tr class='title'>
          <th>$pages->title</th>
      </tr>
      <tr class='info'>
          <td class='type static'>Type: </td>
          <td class='type dynamic'>$pages->type</td>
          <td class='auteur static'>Written by: </td>
          <td class='auteur dynamic'>$pages->author</td>
      </tr>
      <tr class='article'>
          <td colspan='4'>$pages->article</td>
      </tr>
      <tr class='btns'>
          <td colspan='4'>
             <button type='button' class='more'>
                  See more
             </button>
             <button type='button' class='less'>
                  See less
             </button>
          </td>
      </tr>
</table>"

由于有多篇文章并且它们很长,我想使用display: none;隐藏文章,直到用户单击"查看更多"按钮。

我用下面的jQuery代码做到了这一点:

var main = function() {
$('#search_container .preview').hover(function(){
    $(this).toggleClass('active');
});
$('#search_container .active .more').click(function(){
    console.log('click');
    $('#search_container .active .less').show();
    $('#search_container .active .article').show();
    $('#search_container .active .more').hide();
    $('#search_container .active .info').hide();
});
$("#search_container .active .less").click(function(){
    $('#search_container .active .less').hide();
    $('#search_container .active .article').hide();
    $('#search_container .active .more').show();
    $('#search_container .active .info').show();
});
};
$(document).ready(main);

由于只需要显示所选文章,因此我决定添加第一个功能。但是,.active .more.active .less的选择器似乎不起作用,因为当我在没有.active选择器的情况下执行完全相同的代码时,它可以工作并且所有文章和按钮都被显示或隐藏。

知道我该如何解决这个问题吗?

好问题。这与所使用的选择器的范围有关。在你的 JavaScript 中,你提供了一种切换类的机制,但是当你改变类时,你必须重新运行你的 jQuery 选择器来查找新添加的活动类。对javascript代码进行一些小的更改应该会让你朝着正确的方向前进:

var main = function() {
    $('#search_container .preview').hover(
        function(){
            // Keeping this for your targeting
            $(this).addClass('active');
            $(this).find('.more').click(
                function(){
                    $('#search_container .active .less').show();
                    $('#search_container .active .article').show();
                    $('#search_container .active .more').hide();
                    $('#search_container .active .info').hide();
                }
            );
            $(this).find('.less').click(
                function(){
                    $('#search_container .active .less').hide();
                    $('#search_container .active .article').hide();
                    $('#search_container .active .more').show();
                    $('#search_container .active .info').show();
                }
            );
        },
        // When exiting hover, unbind the click bindings
        function(){
            // Keeping this for your targeting
            $(this).removeClass('active');
            // These keep only one .preview container bound to the commands
            // at a given moment
            $(this).find('.more').unbind('click');
            $(this).find('.less').unbind('click');
        }
    );
};
$(document).ready(main);

这种实现有几个缺点。每次悬停时,都会注册点击事件。每次模糊显示时,都会取消设置单击绑定,以防止后续悬停双重绑定单击事件。由于您所有的目标类都包含在.preview因此我甚至可以执行以下操作:

var main = function() {
    var previews = $('#search_container .preview');
    $.each(
        previews,
        function(){
            // Reference stored for the .preview container
            var ref = $(this);
            ref.find('.more').click(
                function(){
                    ref.find('.less').show();
                    ref.find('.article').show();
                    ref.find('.more').hide();
                    ref.find('.info').hide();
                }
            );
            ref.find('.less').click(
                function(){
                    ref.find('.less').hide();
                    ref.find('.article').hide();
                    ref.find('.more').show();
                    ref.find('.info').show();
                }
            );
        }
    );
};
$(document).ready(main);

现在,所有预览都将.more.less项绑定到单击事件,并且单击事件在.preview范围内运行,允许一次注册所有项目。希望这有帮助。

我认为

原因是,当您创建事件侦听器时,DOM 节点尚未准备就绪。因为没有元素有活动类。而是尝试下面的脚本

var main = function() {
$('#search_container .preview').hover(function(){
    $(this).toggleClass('active');
});
$('#search_container').on('click', '.active .more', function(){
    console.log('click');
    $('#search_container .active .less').show();
    $('#search_container .active .article').show();
    $('#search_container .active .more').hide();
    $('#search_container .active .info').hide();
});
$('#search_container').on('click', '.active .less', function(){
    $('#search_container .active .less').hide();
    $('#search_container .active .article').hide();
    $('#search_container .active .more').show();
    $('#search_container .active .info').show();
});
};
$(document).ready(main);

这将在主容器上添加一个live事件侦听器,并等待任何元素匹配.active .more

问题是因为您正在动态添加/删除.active类。在加载页面时,它不存在于任何元素上,因此没有绑定任何事件处理程序。

若要解决此问题,请使用委托的事件处理程序:

var main = function() {
  $('#search_container .preview').hover(function() {
    $(this).toggleClass('active');
  });
  $('#search_container').on('click', '.active .more', function() {
    $(this).find('.active .less, .active .article').show();
    $(this).find('.active .more, .active .info').hide();
  }).on('click', '.active .less', function() {
    $(this).find('.active .less, .active .article').hide();
    $(this).find('.active .more, .active .info').show();
  });
};
$(document).ready(main);

最新更新