重新配置DOM无法正常工作

时间:2016-06-22 04:06:13

标签: javascript html dom

div我有几个孩子(不是固定金额)。有text input允许用户输入数字。

然后有function organizeNumberOfRows根据input中的号码组织孩子。让我举个例子。我们假设我有4个孩子,text input的数量为3个。organizeNumberOfRows会为每3个孩子创建一个div并将其添加到父元素中。< / p>

结果层次结构:

  • 4个孩子,input 3:#parentElem > .innerWrapper > (.child * 3) + .innerWrapper > .child
  • 4个孩子,input 2:#parentElem > .innerWrapper > (.child * 2) + .innerWrapper > (.child * 2)

希望这很清楚。

每次text input更改时,我都必须重新配置dom。我这样做的方式是(function clearTiles),我将所有子元素添加到var div,然后调用organizeNumberOfRows

当我致电organizeNumberOfRows时(在我更改textInput之后),没有任何反应。如何在text input

中插入号码后重新配置孩子

JSFiddle

&#13;
&#13;
var parentTileElement = document.getElementById('parentTileElement'),
  amountOfRowsInput = document.getElementById('amountOfRows');

function NumberOfRows( /** Int */ defaultValue) {
  var value = defaultValue;

  this.set = function(val) {
    value = val;
    var parent = clearTiles();
    console.log(parent, val);
    organizeNumberOfRows(val, parent);
  };
  this.get = function() {
    return parseInt(value);
  }
}
var _numberOfRows = new NumberOfRows(3);
var _outerTilesWrapper = document.createElement('div');
var _innerTilesWrapper;

amountOfRows.addEventListener('keyup', function(e) {
  _numberOfRows.set(this.value);
});

organizeNumberOfRows(_numberOfRows.get(), parentTileElement);

function organizeNumberOfRows( /** Int */ numberOfRows, /** DOM Element */ parentElem) {
  while (parentElem.children.length) {
    var currentTile = parentElem.children[0];
    if (typeof _innerTilesWrapper === 'undefined' || _innerTilesWrapper.children.length === numberOfRows) {
      _innerTilesWrapper = document.createElement('div');
      _innerTilesWrapper.className = 'innerWrapper';
      _outerTilesWrapper.appendChild(_innerTilesWrapper);
    }
    _innerTilesWrapper.appendChild(currentTile);
  }
  parentTileElement.appendChild(_outerTilesWrapper);
}

function clearTiles() {
  var tempDiv = document.createElement('div');
  var innerTileWrappers = parentTileElement.firstElementChild.children;

  while (innerTileWrappers.length) {
    while (innerTileWrappers[0].children.length) {
      tempDiv.appendChild(innerTileWrappers[0].children[0]);
    }
    parentTileElement.firstElementChild.removeChild(innerTileWrappers[0]);
  }
  parentTileElement.removeChild(parentTileElement.firstElementChild);
  return tempDiv; /** DOM Elem */
}
&#13;
body {
  margin: 0;
}
#outerTileWrapper {
  display: flex;
  flex-wrap: wrap;
}
#tileWrapper {
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
}
.tile {
  width: 100px;
  height: 100px;
  background-color: lightgreen;
  list-style: none;
  border: 1px solid black;
}
&#13;
<div id="parentTileElement">
  <div class="tile">01</div>
  <div class="tile">02</div>
  <div class="tile">03</div>
  <div class="tile">04</div>
</div>

<input type="text" id="amountOfRows">
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

你已经让这变得不必要了。我不知道你为什么在这里使用构造函数,因为代码在大多数部分使用函数样式。

您可以将切片移动到包装器元素,然后移除clearTiles函数中的内包装器。现在organizeNumberOfRows函数可以根据新值重新启动进程。

请注意,以下代码段使用了一些ES2015功能,您可以使用ES5替换它们(箭头功能和let关键字)。

var parentTileElement = document.getElementById('parentTileElement'),
    amountOfRowsInput = document.getElementById('amountOfRows'),
    tiles = [].slice.call(parentTileElement.querySelectorAll('.tile'));

function NumberOfRows( /** Int */ defaultValue = 3) {
    this.set = function(val) {
        this.value = +val;
        clearTiles();
        organizeNumberOfRows(this.value);
    };
    this.get = function() {
        return this.value;
    }
    this.set(defaultValue);
}
var _numberOfRows = new NumberOfRows(3);

amountOfRows.addEventListener('keyup', function(e) {
    _numberOfRows.set(this.value);
});

function organizeNumberOfRows( /** Int */ numberOfRows) {
    for (var i = 0, j = tiles.length; i < j; i += numberOfRows) {
       let wrapper = document.createElement('div');
       wrapper.className = 'innerWrapper';
       tiles.slice(i, i + numberOfRows).forEach(el => wrapper.appendChild(el) );
       parentTileElement.appendChild(wrapper);
    }
}

function clearTiles() {
    tiles.forEach(el => parentTileElement.appendChild(el) );
    [].forEach.call(parentTileElement.querySelectorAll('.innerWrapper'), el => {
        parentTileElement.removeChild(el);    
    });
}

以下是更新的演示:https://jsfiddle.net/zzn1s2sj/

如果要在文档中添加许多{#,.}parentTileElement元素,则应修改代码。以下代码适用于许多包装元素。

// Some utility functions for querying the DOM
var findOne = sel => document.querySelector(sel);
var findMany = (sel, el) => {
  el = typeof el !== 'undefined' ? el : document;
  return Array.prototype.slice.call(el.querySelectorAll(sel)); 
}

function NumberOfRows(parentEl, chunkCount) {
    this.innerWrappers = []
    this.parent = parentEl;
    this.tiles = findMany('.tile', this.parent);
    this.chunkCount = chunkCount || 3;
    this.organize();
}
NumberOfRows.prototype.setChunk = function(val) {
   if ( +val < 1 || isNaN(+val) ) {
      throw new Error('The passed value should be a number more than 0, "' + val + '" given.');
   }
   this.chunkCount = +val;
   this.organize();
}

NumberOfRows.prototype.getChunk = function() {
   return this.chunkCount;
}

NumberOfRows.prototype.clearWrappers = function() {
    this.tiles.forEach(el => this.parent.appendChild(el) );
    this.innerWrappers.forEach( el => this.parent.removeChild(el) );
    this.innerWrappers = [];
}

NumberOfRows.prototype.organize = function() {
    this.clearWrappers();
    for (var i = 0, j = this.tiles.length; i < j; i += this.chunkCount) {
       let wrapper = document.createElement('div');
       wrapper.className = 'innerWrapper';
       this.tiles.slice(i, i + this.chunkCount).forEach(el => wrapper.appendChild(el) );
       this.parent.appendChild(wrapper);
       this.innerWrappers.push(wrapper);
    }
}

// Usage:
var _numberOfRows = new NumberOfRows(findOne('#parentTileElement'), 3);
findOne('#amountOfRows').addEventListener('keyup', function(e) {
    _numberOfRows.setChunk(this.value);
});

https://jsfiddle.net/12avgste/