javascript - 循环多个元素并向每个元素添加一个包装器

标签 javascript

在等待人们来过圣诞节的时候,我尝试用 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/

相关文章:

javascript - Firebase 应用的 Mocha 单元测试

javascript - 给定时间和当前时间之间的进度条

javascript - Webpack:提取文本插件和代码分割

javascript - 关于javascript中的函数

javascript - ASP.NET MVC - AJAX 提交表单不会触发适当的事件

javascript - Try 语句永远不会在不抛出错误的情况下通过

javascript - 对特定 IP 而非全局应用速率限制登录 api

javascript - 动态下拉菜单,$_GET 带空格

javascript - 我可以在 onclick 函数中设置一个值吗?

javascript - ASP.NET MVC 将 json 数组作为常规发布请求提交给 Controller (nonajax)