我目前正在构建一个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);