JS移动DOM节点,将某节点下所有子节点移动(剪切)到另一个节点下。新手很容易踩的坑!

JS移动DOM节点,将某节点下所有子节点移动(剪切)到另一个节点下。新手很容易踩的坑!


重点:移动完一个非尾部节点之后,后面的节点会依次部位上来,并且节点数据的长度会实时变化!!

题目(新手练习题)

将上方绿色实线框中的两个列表移动(剪切)到下方绿色虚线框中。
ps:
1、绿色实线框被一个div包裹,绿色虚线框被一个div包裹;
2、绿色实线框中的子节点有两个,分别是圆点样式的列表和圆圈样式的列表。
3、要求点击下方的剪切按钮,将绿色实线框中的两个子节点移动到绿色虚线框中。
4、若div中仅有一个节点,那么这道题很简单,没有什么坑,但是多个节点就可能会踩坑~~~
JS移动DOM节点,将某节点下所有子节点移动(剪切)到另一个节点下。新手很容易踩的坑!

BUG

先行知识点:
1、节点A.appendChild(节点B);若B为新创建的节点,则将节点B添加为节点A的子节点。
1、节点A.appendChild(节点B);若B为另外一个节点的子节点,则将节点B剪切到节点A的子节点。

第一种错误

代码如下:

			function cut_bug(){
				var upperDiv = document.getElementById("div1"); //通过id获取上方div节点
				var upperUl = upperDiv.children; //取上方div节点的所有子节点
				
				var belowNode = document.getElementById("div2"); //通过id获取下方div节点
				
				//我们先不用循环,用最简单的方式,试着将子节点移动过去
				belowNode.appendChild(upperUl[0]);
				belowNode.appendChild(upperUl[1]);
			}

运行结果如下:
JS移动DOM节点,将某节点下所有子节点移动(剪切)到另一个节点下。新手很容易踩的坑!
解析:
UncaughtTypeError: Failed to execute ‘appendChild’ on ‘Node’: parameter 1 is not of type ‘Node’.
未捕获的类型错误:不能在节点上执行appendChild操作:参数1不是节点类型。

从错误中可以看出,参数0没有问题,而参数1出了问题;利用upperDiv.childElementCount方法获取upperUl数组的长度,可以看出长度为2,确实是应该从upperUl数组中获取两次数据。
实际上,每执行一次移动操作,节点就会实时减少,我们从首部直接取出第0个,那么第1个元素会直接补位来到第0个。
所以,我们可以每次都取0,取upperUl数组的长度次;我们还可以从尾部取到头部(注意:尾部这样的方式会使剪切之后所有元素倒过来)。具体实现代码在后面。

第二种错误

代码如下:

function cut_bug(){
				
				var upperDiv = document.getElementById("div1");
				var upperUl = upperDiv.children;
				
				var belowNode = document.getElementById("div2");
				
				//我们不妨试试从上面吸取教训,每次取0,再加入循环的操作
				for (var i = 0; i < upperUl.length; i++) {
					belowNode.appendChild(upperUl[0]);
				}
			}

运行结果如下:
JS移动DOM节点,将某节点下所有子节点移动(剪切)到另一个节点下。新手很容易踩的坑!
解析:
这次没有报错,但是运行结果好像有点差强人意啊,怎么就只移动了一个呢?
问题出在for (var i = 0; i < upperUl.length; i++) 的i < upperUl.length,因为upperUl.length是实时变化的,i每增加一次(append成功一次),upperUl.length就减少一次,结果就是,如果共有n个子节点,最后只能移动n/2个子节点。
所以,我们可以每次利用一个变量在循环之前(append操作之前)存储upperUl.length,保证i的循环终止条件不变。

解决方案

第一种解决方案(无循环)

//这个剪切完之后是正序的。
function cut(){

			var upperDiv = document.getElementById("div1");
			var upperUl = upperDiv.children;
			var len = upperDiv.childElementCount;
			
			var belowNode = document.getElementById("div2");
			
			belowNode.appendChild(upperUl[0]);
			belowNode.appendChild(upperUl[0]);
		}

//这个剪切完之后是反序的。
function cut(){

			var upperDiv = document.getElementById("div1");
			var upperUl = upperDiv.children;
			
			var belowNode = document.getElementById("div2");
			
			belowNode.appendChild(upperUl[1]);
			belowNode.appendChild(upperUl[0]);
		}

第二种解决方案

//这个剪切完之后是反序的。
function cut(){
				
				var upperDiv = document.getElementById("div1");
				var upperUl = upperDiv.children;
				var len = upperDiv.childElementCount;
				
				var belowNode = document.getElementById("div2");
				
				for (var i = len - 1; i >=0; i--) {
					belowNode.appendChild(upperUl[i]);
				}
			}

第三种解决方案(推荐)

function cut(){
				
				var upperDiv = document.getElementById("div1");
				var upperUl = upperDiv.children;
				var len = upperDiv.childElementCount;
				
				var belowNode = document.getElementById("div2");
				
				for (var i = 0; i < len; i++) {
					belowNode.appendChild(upperUl[0]);
				}
			}

总结

移动完一个非尾部节点之后,后面的节点会依次部位上来,并且节点数据的长度会实时变化!!

刚刚接触JS,想着记录一下自己遇到的问题,如果能帮到大家就更好了,有错误希望大家提出来~~

上一篇:javascript简单案例-动态表格


下一篇:vue如何引入script的在线链接