循环访问多个元素并为每个元素添加一个包装器

Looping on multiple elements and add a wrapper to each of them

本文关键字:元素 一个 包装 访问 循环 添加      更新时间:2023-09-26

在等待人们来过圣诞节时,我尝试用香草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 而且我无法通过它。知道吗?

这是一个小提琴来实时检查它

您需要使用:

document.querySelectorAll('.materialFloatLabel' + i)[0]

即使只返回一个元素。

根据MDN规范:

elementList = document.querySelectorAll(selectors);
// elementList is a non-live NodeList of element objects.

NodeList是一些类似数组的对象。


在代码中:

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 规范)。由于您要将输入移动到 wrapper 上,这还没有在 DOM 上,因此您的querySelectorAll返回为空。

以及更多

不要每次都执行this.input(),因为你的 DOM 正在发生变化。如果你不小心,你的循环可能会变得一团糟。由于querySelectorAll的结果不是实时的,因此您可以保持选择结果的一致性。

更重要的是,为了获得更好的性能,最好将中间结果存储在一些变量中。

下面是一个工作示例:http://jsfiddle.net/18fxv7yr/1/