深入了解parentNode,parentElement,childNodes,children的区别,一看就懂

今天是准备面试的第七天,js是由ECMAScript、文档对象模型(DOM)和浏览器对象模型(BOM)组成,我们今天就了解下与DOM有关的常用接口parentNode,parentElement,childNodes,children。
在这里插入图片描述
parentNode,parentElement,childNodes和children都是对节点的操作,因此我们需要对dom树有一定的了解,在文档对象模型中,每一部分都是由节点组成(包括document都是一个节点),节点的类型一共有三种:元素节点,属性节点,文本节点,由上面的图可以看出属性节点是元素节点的一个分支,一般不会考虑。

一、childNodes和children的区别

1、childNodes

返回当前元素子节点的所有类型节点(包括:空格和换行符都会都会被默认成文本节点

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div class="parent">
			<ul>
				<li>1</li>
				<li>2</li>
				<li>3</li>
				<li>4</li>
			</ul>
		</div>
		<script type="text/javascript">
			var ul = document.querySelector('ul')
			console.log(ul.childNodes);
			console.log(ul.childNodes.length);
		</script>
	</body>
</html>

在这里插入图片描述
是不是很奇怪,为什么有这么多文本节点?我们打开看看,这些文本的内容是什么
在这里插入图片描述
这说明,该节点下的回车符和空格也会被childNodes当成文本节点,我们尝试着给li元素节点添加属性,我们会发现length的长度还是没有改变,也就是在说childNodes只返回文本节点和元素节点
有些不怀好意的人会说,我不想要回车空格的文本节点,这应该怎么办呢?
那我们需要知道每个节点都会有nodeType属性

  1. nodeType === 1 该节点为元素节点
  2. nodeType === 2 该节点为属性节点
  3. nodeType === 3 该节点为文本节点

我们就要用这个属性的特点来只获取元素节点

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div class="parent">
			<ul>
				<li>1</li>
				<li>2</li>
				<li>3</li>
				<li>4</li>
			</ul>
		</div>
		<script type="text/javascript">
			const ul = document.querySelector('ul');
			const childNodes = ul.childNodes;
			let temp = 0;
			let newNodes = [];
			for(let i = 0; i < childNodes.length; ++i){
				if(childNodes[i].nodeType === 1){
					newNodes[temp++] = childNodes[i];
				}
			}
			console.log(newNodes);
		</script>
	</body>
</html>

在这里插入图片描述
这样就得到了我们想要的结果,其实我们还可用children属性,来实现这个功能。

2.children

返回当前元素的子元素节点(不返回文本节点和属性节点)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div class="parent">
			<ul>
				<li>1</li>
				<li>2</li>
				<li>3</li>
				<li>4</li>
			</ul>
		</div>
		<script type="text/javascript">
			const ul = document.querySelector('ul');			
			console.log(ul.children);
		</script>
	</body>
</html>

在这里插入图片描述
通过运行我们可以发现,只返回了元素节点,没有返回文本和属性节点

二、区别parentNode和parentElement

parentNode:和英语翻译一样,返回父节点
parentElement:返回父元素
DOM树每一部分都是由节点组成,节点是由元素节点,属性节点,文本节点三部分组成,从这里可以看出节点包含元素节点。从html中又可以知道父节点不可能是文本和属性节点。难道parentNode和parentElement返回的值都是一样的吗?不,不,不,html是根元素,document是一种特殊的节点,当当前节点的父节点是document时,parentNode返回的是#document,而parentElement返回值为空,这就是他们两最大的区别。
我光说可能会有点晕,还是上代码吧

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div class="parent">
			<ul>
				<li>1</li>
				<li>2</li>
				<li>3</li>
				<li>4</li>
			</ul>
		</div>
		<script type="text/javascript">
			const html = document.querySelector('html');			
			console.log(html.parentNode);
			console.log(html.parentElement);
		</script>
	</body>
</html>

在这里插入图片描述
这是我对parentNode,parentElement,childNodes,children四个属性的见解,欢迎大家留言

  • 14
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
没有根节点,那么构建DOM树和初始化treegrid的过程也需要做出相应的调整,帮我修改代码:// 根节点ID和名称 var rootId = "N000"; var rootName = "菜单"; // 获取指定节点下的所有子节点 function getChildren(nodes, id) { var result = []; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.parentIndex === id) { node.children = getChildren(nodes, node.id); result.push(node); } } return result; } // 构建 DOM 树 function buildTree(parentNode, children) { for (var i = 0; i < children.length; i++) { var childNode = children[i]; var tr = $('<tr class="treegrid-' + childNode.id + '"><td>' + childNode.name + '</td></tr>'); parentNode.append(tr); if (childNode.children && childNode.children.length > 0) { var subTable = $('<table></table>'); tr.append(subTable); buildTree($('<tbody></tbody>').appendTo(subTable), childNode.children); } } } // 主程序 const username = 'hzx'; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { if (xhr.status == 200) { var jsonData = JSON.parse(xhr.responseText); var root = { id: rootId, name: rootName, children: getChildren(jsonData, rootId) }; buildTree($('#tree tbody'), root.children); // 初始化 treegrid $('#tree').treegrid({ expanderExpandedClass: 'glyphicon glyphicon-minus', expanderCollapsedClass: 'glyphicon glyphicon-plus' }); } else { alert("请求失败:" + xhr.statusText); } } }; xhr.open("GET", "shouquan.php?username=" + username, true); xhr.send();
最新发布
05-24
修改的代码如下: // 根节点ID和名称 var rootId = "N000"; var rootName = "菜单"; // 获取指定节点下的所有子节点 function getChildren(nodes, id) { var result = []; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.parentIndex === id) { node.children = getChildren(nodes, node.id); result.push(node); } } return result; } // 构建 DOM 树 function buildTree(parentNode, children) { for (var i = 0; i < children.length; i++) { var childNode = children[i]; var tr = $('<tr class="treegrid-' + childNode.id + '"><td>' + childNode.name + '</td></tr>'); parentNode.append(tr); if (childNode.children && childNode.children.length > 0) { var subTable = $('<table></table>'); tr.append(subTable); buildTree($('<tbody></tbody>').appendTo(subTable), childNode.children); } } } // 主程序 const username = 'hzx'; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { if (xhr.status == 200) { var jsonData = JSON.parse(xhr.responseText); var root = { id: rootId, name: rootName, children: getChildren(jsonData, rootId) }; var tbody = $('<tbody></tbody>'); buildTree(tbody, root.children); $('#tree').append(tbody); // 初始化 treegrid $('#tree').treegrid({ expanderExpandedClass: 'glyphicon glyphicon-minus', expanderCollapsedClass: 'glyphicon glyphicon-plus' }); } else { alert("请求失败:" + xhr.statusText); } } }; xhr.open("GET", "shouquan.php?username=" + username, true); xhr.send(); 主要修改如下: 1. 将构建的 DOM 树添加到 tbody 中,最后再添加到 #tree 中。 2. 初始化 treegrid 的代码不变,因为 treegrid 是根据 class 来进行初始化的,而不是根据 DOM 树结构。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Top丶super航

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值