【问题标题】:Reconfigure DOM not working correctly重新配置 DOM 无法正常工作
【发布时间】:2016-06-22 04:06:13
【问题描述】:

我在div 有几个孩子(不是固定数量)。有一个text input 可以让用户输入一个数字。

然后有一个function organizeNumberOfRows,它根据input 中的数字来组织孩子。让我举个例子吧。假设我有 4 个孩子,text input 有 3 个。organizeNumberOfRows 将为每 3 个孩子创建一个 div 并将其添加到父元素。

结果层次结构:

  • 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

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 */
}
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;
}
<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">

【问题讨论】:

    标签: javascript html dom


    【解决方案1】:

    你让这变得不必要地复杂了。我不确定您为什么在这里使用构造函数,因为代码在大多数情况下都使用功能样式。

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

    请注意,下面的 sn-p 使用了一些 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/

    【讨论】:

    猜你喜欢
    • 2020-03-26
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    相关资源
    最近更新 更多