【问题标题】:jQuery toggle dynamically created elementsjQuery 切换动态创建的元素
【发布时间】:2017-01-19 13:53:35
【问题描述】:

我有这样的东西,但它不起作用:

<!-- ... code .. -->

var id = 0;        

data.forEach(function(item, i) {
      id = id+1;

$( ".button-" + id ).click(function() {
$( ".button-" + id ).toggle();

});

<!-- ... code .. -->

我想要什么:有一些 DIV,例如 button-1、button-2 ... 等等。我做了一个切换,我想用这个循环来自动化它,因为内容是动态生成的。但这似乎是错误的方式......在这个循环中它不起作用。

那么如何为 button-1、button-2、... 进行动态切换??

差不多就是这个,好像是错的:

$( ".button-" + id ).click(function() {
$( ".button-" + id ).toggle();

编辑

好吧,也许我的问题有点乱????到目前为止,谢谢大家的回答,我真的很感激!但是对我来说没有正确的答案......所以又一次,现在更具体:

我有一些带有材质图标的按钮,它们应该在点击时改变它们的状态。

<a href="" class="likebutton-1"><i class="material-icons">favorite</i></a>
<a href="" class="likebutton-1" style="display:none;"><i class="material-icons">favorite_border</i></a>

HTML内容是动态生成的,所以有likebutton-1,likebutton-2...

然后是另一个 DIV,它显示了许多喜欢:

<div class="likes-1">99 likes</div>
<div class="likes-1" style="display:none;">100 likes</div>

DIV 都在一个外部容器中。

这是我的 jQuery 代码:

$( ".likebutton-1" ).click(function() {
$( ".likebutton-1" ).toggle();
$( ".likes-1" ).toggle();
});      

嗯,该代码对我有用。图标从最喜欢切换到最喜欢的边框,喜欢从 99 切换到 100...(这只是一个演示应用程序,因此不需要真正计算喜欢)

但我也想动态生成该 jQuery 代码,但那是行不通的...现在我必须为 likebutton-1、likebutton-2 手动设置切换...

【问题讨论】:

  • data 变量中有什么?
  • 以上内容太零碎,我们无法提供有意义的帮助。在问题中添加minimal reproducible example,理想情况下使用 Stack Snippets([&lt;&gt;] 工具栏按钮)使其可运行
  • 他的问题将是他的所有点击处理程序都将具有最后一个 forEach 循环的 id 值,因为它们在运行时都引用相同的 id 变量,所以所有按钮都会切换最后一个按钮应该是什么切换。
  • 嘿,抱歉,我对其进行了编辑以使其(希望)更清晰......
  • 不完全相关,但为什么不直接做++id?

标签: javascript jquery html toggle event-listener


【解决方案1】:

根据您的最新更新,我建议您对 HTML 标记进行一些结构更改。

而不是使用:

<a href="" class="likebutton-1"><i class="material-icons">favorite</i></a>
<a href="" class="likebutton-1" style="display:none;"><i class="material-icons">favorite_border</i></a>

我建议只使用一个元素 - 这可以防止样式问题。此外,如果您动态生成这些段,请删除 -1-X 后缀,否则您需要大量(动态创建的)事件侦听器。

这样做:

<a href="#" class="likebutton"><i class="material-icons icon-fav">favorite</i></a> 

我已将 icon-fav 类添加到您的元素中,以便提前更轻松地访问它。

现在我们对您的喜欢部分做同样的事情并改进代码结构。将喜欢计数(所以数字)与文本分开。所以我们可以很容易地增加或减少这个数字。

<div class="likes"><span class="likes-count">99</span> likes</div>

因为你提到你会自动生成这些片段,所以我假设你在这些元素周围有一个或类似的东西,比如:

<div class="parent-container">
  <a href="#" class="likebutton"><i class="material-icons icon-fav">favorite</i></a>  
  <div class="likes"><span class="likes-count">99</span> likes</div>
</div>

现在我们关心剩下的——JavaScript。

我们需要一些树遍历,因为删除了类的 -x 后缀 - 否则我们会在单击其中一个元素时立即更改所有元素。你可以在这里找到更多关于jQuery Tree Traversal的信息。

$(".likebutton").click(function() {
    var $parent = $(this).closest(".parent-container");
    var likes = parseInt($parent.find(".likes-count").text());

    if($parent.find(".icon-fav").text() == "favorite") {
        $parent.find(".icon-fav").text("favorite_border");
        $parent.find(".likes-count").text(++likes);
    }
    else {
        $parent.find(".icon-fav").text("favorite");
        $parent.find(".likes-count").text(--likes);
    }
});   

此事件侦听器使用 .closest() 方法找到其父容器,即使您的代码嵌套更多,也可以使此代码正常工作。这个$parent 变量是所有后续查询的搜索库。我使用.find() 一直向上遍历——如果有必要的话——因为你可能有一个更嵌套的结构。

这是working jsfiddle!试一试。

【讨论】:

  • 哇,太好了!!非常感谢...完全解决了我的问题,它比我最初的方法更优雅:-)
【解决方案2】:

我想这就是你的意思:D

https://jsfiddle.net/1eo4b33m/1/

$("[class*=button-]").click(function(){
    $(this).toggle()
})

【讨论】:

  • 如果按钮添加了其他类并且上述方法不起作用,也许还有"[class*=button-]"
  • 虽然它也适用于foobutton-类,但我认为如果有多个类最好不适用,已编辑。
  • 当然,这两种解决方案都不是 100% 稳健的,根据 OP 的情况,任何一种都可能适合。
  • 嘿...嗯,试过了,但按钮没有切换,而是消失了。我有两个 button-1, button-2 ... 在每种情况下都有一个是 display:none; (如果我手动切换,则切换有效......但不适用于此解决方案)
  • 这有效(我的手动解决方案): $( ".button" ).click(function() { $( ".button" ).toggle(); });
【解决方案3】:

试一试吧! :)

$("[class*='button-']").click(function(){
    $(this).toggle();
});

【讨论】:

    【解决方案4】:

    你必须在这里使用闭包,

    var id = 0;   
    
    data.forEach(function(item, i) {
          id = id+1;
          var bindEvents = function theOutterFunction() {     
            return function() {
            $( ".button-" + id ).click(function() {
            $( ".button-" + id ).toggle();
           }
          }();
          bindEvents();
    });
    

    【讨论】:

    • 括号有点乱...我得到一个空白页,但在这里找不到错误。编辑:修复它。但是还是不行……嗯 :(
    【解决方案5】:

    你有一些很好的答案。但看起来你错过了这有多简单。您需要使用的是jQuery's .on 方法。您可以查看SO Q&A,了解有关设置动态事件的更多信息。

    但是,总而言之,它的意思是:“将动态元素的事件分配给静态父级”。阅读此处以获取有关"What is dynamic and static" 的更多信息。简而言之,动态是指页面加载后创建的。

    所以本质上,你可以使用Jamie Phan给出的answer,你只需要了解如何实现它。

    您真正需要的只是一个“静态父级”。这是加载页面时已存在于 HTML 中的元素。我个人经常使用 DOM 对象,但是,最好的做法是有一个具有 ID 的近亲。例如,如果您的 HTML 看起来像:

    <div>
        <h1>Dynamic buttons added below</h1>
        <ul id="divDyno"><!-- Buttons will be added here --></ul>
    </div>
    

    那么您的静态父级将是&lt;div id="divDyno"...,可以使用字符串'#divDyno' 进行选择。因此,您的代码如下所示:

    $('#ulDyno').on('click', '[class*=button-]', function(e) {
        $(this).toggle();
    })
    

    以下是如何轻松实施这些技术的快速示例。我添加了一些内容,以便您可以看到它的完整功能,但我会尝试深入解释所有内容。

    修改为简单地切换按钮的类(也称为更改状态)

    /** This will be the event fired when clicking on a "dynamically" created button **/
    function button_click_event() {
    	//	only need use "this", no need for ID.
    	//	'this' is the button html element itself
    	$(this).toggleClass('black white');
    }
    
    /** This event will dynamically create buttons **/
    function create_button() {
    		// first I get the length of how many buttons exist,
    		// simply to add to the button text
    	var len = $('ul li').length,
    		//	then I create a <li> to append to the <ul>
    		li = $('<li />').appendTo('ul'),
    		//	then, of course, I create the <button> and add it to the <li>
    		btn = $('<button />').text('Button '+len).addClass('button-'+len).appendTo(li);
    	//	now we'll give the button a class for color
    	btn.addClass(len%2 ? 'black': 'white')
    }
    
    /** This will simply show all "toggled" buttons **/
    function show_buttons() {
    	$('ul button').show();
    }
    $(function() {
    	//	As per the previously mentioned example
    	//	In jQuery, you can set events for a dynamic element by using a static parent.
    	$('#ulDyno').on('click', '[class*=button-]', button_click_event)
    	
    	//	In the following case, I'll simply use the DOM for brevity,
    	//		but it's still best to use a "static" element with an ID
    	//	This event is simply for the "Add" button. To "dynamically" create buttons.
    	$(document).on('click', '#btnAdd', create_button)// notice i didn't close with a ";"
    		//	With no close, the return is "$(document)", So I can write more code attached to it.
    		//	This event will show any "toggled" buttons
    		.on('click', '#btnShow', show_buttons);
    });
    html, body { font-size: 20px; width: 100%; }
    html, body, table { height: 100%; margin: 0 auto; padding: 0; text-align: center; }
    div { left: 1em; position: fixed; top: 1em; }
    ul { margin: 0 auto; padding: 0; }
    li { list-style: none; margin: .5em auto; padding: 0; }
    button { padding: .5em .8em; }
    .black { background-color: #000; color: #fff }
    .white { background-color: #fff; color: #000 }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div><button id="btnAdd">Add Buttons</button><button id="btnShow">Show All Buttons</button></div>
    <table>
    	<tr>
    		<td>
    			<br />
    			<ul id="ulDyno"></ul>
    		</td>
    	</tr>
    </table>

    【讨论】:

    • 非常感谢!但问题仍然存在,我的按钮消失了。我想将按钮更改为另一个。这适用于 .toggle,因为我有两类它,一类是 display:none。所以它在这两者之间切换。但只有当我为每个数字/ID手动执行...但使用您的解决方案时,它才会消失而不是改变状态。你知道我的意思吗?
    • @Kabalaba 老实说......不。我不听你说的。试着一步一步地引导我完成你“期望”完成的事情,我会尽力调整我的答案
    • @Kabalaba 已经改变了,看看例子,告诉我你的想法?
    猜你喜欢
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 2013-01-21
    • 2011-03-23
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多