在等待人们来过圣诞节的时候,我尝试用 vanilla JS 启动一个类似 floatlabel 的库。我陷入了在输入周围添加包装器的部分
var materialFloatLabel = function(o) {
o = (typeof o === 'undefined') ? '' : o;
var lib = {
// Just for the futur settings
settings: {
selector: o.selector ? o.selector : '.matFloat'
},
// Getting the inputs
inputs: function() {
return document.querySelectorAll(this.settings.selector);
},
// Adding a specific class to each input so it can easily be selected later
addWrapper: function() {
for(var i = 0; i < this.inputs().length; i++) {
this.inputs()[i].className = this.inputs()[i].className + ' materialFloatLabel' + i;
var wrapper = document.createElement('div');
wrapper.appendChild(this.inputs()[i]);
// ERROR DOWN HERE
document.querySelectorAll('.materialFloatLabel' + i).parentNode.replaceChild(wrapper, document.querySelectorAll('.materialFloatLabel' + i));
}
},
init: function() {
this.addWrapper();
}
};
return lib.init();
};
(function() {
materialFloatLabel();
})();
我当前遇到的错误是Uncaught TypeError: Cannot read property 'replaceChild' of undefined
而且我无法设法解决它。有什么想法吗?
这里是a fiddle实时查看
最佳答案
您需要使用:
document.querySelectorAll('.materialFloatLabel' + i)[0]
即使只返回一个元素。
根据MDN spec :
elementList = document.querySelectorAll(selectors);
// elementList is a non-live NodeList of element objects.
而 NodeList
是一些 array-like object .
在代码中:
for(var i = 0; i < this.inputs().length; i++) {
this.inputs()[i].className = this.inputs()[i].className + ' materialFloatLabel' + i;
// Create a Node, which is NOT on DOM yet.
var wrapper = document.createElement('div');
// MOVE the input to the new Node, so the input is not on DOM anymore!
wrapper.appendChild(this.inputs()[i]);
// Since the input is not on DOM, querySelectorAll('.materialFloatLabel' + i) returns []
document.querySelectorAll('.materialFloatLabel' + i)[0].parentNode.replaceChild(wrapper, document.querySelectorAll('.materialFloatLabel' + i)[0]);
}
添加新类后无法查询输入,因为输入不再位于 DOM 上。请注意,appendChild
会将节点移动到新位置(MDN Spec)。由于您要将输入移动到尚未在 DOM 上的 wrapper
,因此您的 querySelectorAll
返回空。
还有更多
不要每次都执行 this.input()
,因为您的 DOM 正在发生变化。如果你不小心,你的循环可能会变得一团糟。由于 querySelectorAll
的结果不是实时的,因此您可以保持选择结果一致。
更重要的是,为了获得更好的性能,最好将中间结果存储在一些变量中。
这是一个工作示例:http://jsfiddle.net/18fxv7yr/1/
关于javascript - 循环多个元素并向每个元素添加一个包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27643352/