如何克隆元素及其相关的事件回调函数?

3
我正在克隆一个元素并将其添加到DOM中。我原以为新创建的克隆元素内部的this指向自身,但实际上它似乎指向原始克隆元素。
为了说明这一点,我创建了以下脚本。点击“cloneIt”后,会添加一个新元素,然后单击新元素时,this将指向原始克隆元素。我的愿望是data('type')显示“added”。
如何克隆一个元素并使回调适用于新克隆的对象? https://stackoverflow.com/
$('.fileupload').fileupload({
    start: function (e, data) {
        console.log('start', this, $(this).parent().data('type'));
    }
})
    .on('fileuploadsubmit', function (e, data) {
    console.log('fileuploadsubmit', this, $(this).parent().data('type'));
});

$('#cloneIt').click(function () {
    $('#clone').clone(true).removeAttr('id').data('type', 'added').appendTo('#container');
});

#clone {
    display:none;
}

<button id="cloneIt">cloneIt</button>
<ul id="container">
    <li id="clone" data-type="clone">
        <input class="fileupload" name="file" type="file" />
    </li>
    <li data-type="existing">
        <input class="fileupload" name="file" type="file" />
    </li>
</ul>

不确定您确切想要什么,但是如果您定义 $('.fileupload'),然后再创建克隆,它将不会被包括在内。仅更改数据属性似乎只有在使用.attr('data-type','added')时才有效。 - Shikkediel
@Shikkediel .attr() 提供了相同的结果。请参见 http://jsfiddle.net/fq4rqc1u/5/。我将 $('.fileupload') 应用到 #clone 和具有 data-typeexisting 的另一个单个 input 上,这两者似乎都有效。然而,当我克隆时,它仍然保留着现有的数据值。也许需要某种回调函数来代替直接访问 this - user1032531
console.log($(this).parent().index()); 会输出什么? - Roamer-1888
@Roamer-1888 编辑:0 - user1032531
好的,那符合你所说的 - 在开始回调函数中,this 可靠地指向原始元素,而不是克隆元素。 - Roamer-1888
2个回答

2

看起来,当调用.fileupload()时,start回调函数中的this概念被锁定,并且这个this会传递到克隆对象。

个人建议将模板LI与现有的LIs分开,并且不要在模板上调用.fileupload()

HTML

<button id="cloneIt">cloneIt</button>
<ul id="template">
    <li data-type="original">
        <input class="fileupload" name="file" type="file" />
    </li>
</ul>
<ul id="container">
    <li data-type="existing">
        <input class="fileupload" name="file" type="file" />
    </li>
</ul>

CSS

#template {
    display:none;
}

最初,只在#container中的输入框上调用.fileupload(),之后在制作出来的任何模板克隆品上调用它。

Javascript

$('#container .fileupload').fileupload({
    start: function (e, data) {
        console.log('start', this, $(this).parent().data('type'));
    }
}).on('fileuploadsubmit', function (e, data) {
    console.log('fileuploadsubmit', this, $(this).parent().data('type'));
});

$('#cloneIt').click(function () {
    $('#template li').clone().data('type', 'clone').appendTo('#container').find('.fileupload').fileupload(...);
});

我建议对于任何插件都采用这种方法。克隆小部件化的元素是很危险的。克隆的行为不能保证可靠性。对于某些插件,你可以成功,但对于其他插件,则可能不行。


1

http://jsfiddle.net/1as47aeb/5/

似乎您需要再次从库中调用fileupload方法,创建DOM对象后。
如果您检查代码中的DOM,您会发现该属性已添加,并且在克隆后的原始代码内部可以查询它。
修正了在克隆输入上传时两个输入事件都被调用的行为。

谢谢Niloct,是的,我确定这样做会起作用。然而,似乎应该可以从最初克隆的元素访问新创建元素的DOM。 - user1032531
可以。但是似乎也需要初始化fileupload。该属性存在,您可以检查DOM,注释掉我在代码底部引入的fileupload,然后您就会看到。 - Niloct

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接