鹰击长空,鱼翔浅底,万类霜天竞自由

使用jQuery的append方法遇到的坑


今天下午在改一个项目的Bug,前端使用的是jQuery,需求大概是这样的:页面上有两个轮播图,要使用JavaScript为每个轮播图动态添加元素,然后为元素添加相应的事件。由于之前的代码对于每个轮播图有单独的处理部分,这是背景。

let element = $(html_template);
$('.carousel').append(element);
element.click(function() { ... });

后来发现事件无论如何都添加不上,事先有一丝这样的怀疑:jQuery的remove()方法,dom元素移除以后,再重新添加到父元素后,事件会消失。会不会和这种情况类似,但是这种情况没有调用remove()方法。而且根据经验,这种推想完全不成立的。

我就改变了一下思路,这个画面上的element是否和代码中element变量一致,我将代码改成了这样的:

element.addClass('foo');
console.log(element[0] === $('.foo')[0]);

结果再控制台上看到了令人意外的结果:flase。奇怪的是,那页面上的元素是来自哪里的?!那代码中的element又在页面的哪里呢?

有两种可能,页面上只有一个element元素,而这个元素不是来自代码中的element变量;页面上有两个element元素,一个来自代码中的element变量,另一个不从得知。很明显第一种可能性是不存在的,或者说及其没有可信度。使用下面的代码即可验证:

console.log($('.foo').length);
// result is 2.

为什么会出现两个元素呢?代码只执行了一次,却添加了两个元素到页面上,很明显问题肯定在append()方法调用的地方,回过头一看$('.carousel')这行代码,会返回多个元素,所以会为每个元素都追加一个element子元素。

回过头想一想,第二处代码片段返回结果为false,说明我要修改的轮播图控件中添加的元素并不是上下文中的变量,很明显jQuery会把该代码中的变量添加到最后一个选择的元素,也就是第二个轮播图控件,而第一个轮播图控件中的元素是深拷贝的!

问题解决了以后,我发现任何时候,写代码都要用心,不能随便一写。有时候漫不经心的代码,导致的问题,需要用很长的时间取解决。


版权声明

本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。 本站博文除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。