dom语法

143 阅读7分钟

什么是DOM:

Document Object Model(文档对象模型) - 操作HTML文档

将每个元素/标签/文本/属性/注释都会看作是一个DOM节点/元素/对象

      面试题:HTML/XHTML/DHTML/XML?
	1HTML - 网页
	2XHTML - 更严格的网页
	3DHTML - Dynamic:动态的网页,其实并不是新技术,也不是新概念,而是现有技术的一个整合统称:让我们的网页再离线版也能具有动态效果
			DHTML:HTML+CSS+JS
	4XML - 全部自定义,数据格式:淘汰了:JSON数据格式

DOM:原本是可以操作一切结构化文档的 HTML 和 XML,后来为了方便各类开发者分为了3个方向

  1. 核心DOM:【无敌】,既可以操作HTML也可以操作XML 缺点:API比较繁琐,getAttribute/setAttribute()

  2. HTML DOM:只能操作HTML,API简单:缺点:自定义的东西操作不了

  3. XML DOM:只能操作XML - 不会学习他

    开发建议:优先使用HTML DOM,HTML DOM实现不了再用核心DOM补充

DOM树

树根:document - 不需创建,一个页面只有一个document,由js解释器自动创建

作用:通过树根,可以找到想要的DOM元素/节点/对象

每个DOM元素都有三大属性:

  1. elem.nodeType:描述节点类型
                document 节点:9
		element 节点:1
		attribute 节点:2
		text 节点:3`

以前有用:判断xx是不是一个页面元素 - 因为以前我们的方法和你们现在的方法不一样
  1. elem.nodeValue:获取【属性节点】的值

  2. elem.nodeName:获取节点名称/标签名

注意:返回的是一个全大写组成的标签名

通过 关系 获取元素

	父:xx.parentNode
	子:xx.children - 只能找到儿子
	第一个儿子:xx.firstElementChild;
	最后一个儿子:xx.lastElementChild;
	前一个兄弟:xx.previousElementSibling;
	后一个兄弟:xx.nextElementSibling;
        

递归:

简单来说就是函数中再次调用了函数本身,迟早有一天会停下来

何时使用:遍历DOM树,专门用于【遍历层级不明确】的树状结构

如何使用:
   	function 函数名(根){
   		1、第一层要做什么直接做

   		2、判断它有没有下一级,如果有下一级,则再次调用此函数,但是传入的实参是自己的下一级
   	}
   	函数名(实际的根)

   算法:深度优先!优先遍历当前节点的子节点,子节点遍历完才会跳到兄弟节点
   缺点:同时开启大量的函数调用,浪费的内存,只有一个情况:【遍历层级不明确】
       
递归 vs 循环
递归:优点:直观,易用
          缺点:性能较差
循环:优点:性能较好
          缺点:难得一批

遍历层级不明确的API:TreeWalker

缺点:只能遍历层级不明确的DOM树,不能遍历层级不明确的数据

   如何使用:2步
		1、创建TW
			var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ELEMENT);

		2、反复调用tw的nextNode函数找到节点
			while((node=tw.nextNode())!=null){
				node要干什么
			}

直接找元素:

	1、通过HTML的一些特点找元素
		你会的:id/class/标签
		新的:通过name找元素:var elems=document.getElementsByName("name值")

	2、通过css选择器查找元素:2个方法 - 更适合用于复杂查找(多句才能找到最终元素)
		1、var elem=document.querySelector("任意css选择器");
			只会找到一个元素,如何同时匹配多个,也只会返回第一个
			没找到null

		2、var elem=document.querySelectorAll("任意css选择器");
			找到了是一个集合
			没找到是一个空集合

面试题:

	getXXXX和queryXXXX的区别?
		返回的结果不一样:
			1、getXXXX:返回的是一个动态集合HTMLCollection
				特点:每一次DOM树修改过后,js都会悄悄的再次查找元素,保证数据和页面对应,效率相对较低

			2、queryXXX:返回的是一个静态集合Nodelist
				特点:只管查找的一次找出来的结果,后续DOM树的修改,我们的数据也不会变化,效率相对较高
				优点:1、查找简单
				      2、还支持forEach

找元素的方式:

  1. 直接找元素:getXXX、queryXXX
  2. 通过节点的关系
  3. 层级不明确的情况 - 递归

操作元素

元素的内容

	1、*elem.innerHTML:获取或者设置开始标签到结束标签之间的HTML代码,没有兼容性问题,可以识别标签
		获取:elem.innerHTML
		设置:elem.innerHTML="新内容"

	2、elem.textContent:获取或者设置开始标签到结束标签之间的纯文本,但是有兼容性问题,不可以识别标签
		获取:elem.textContent
		设置:elem.textContent="新文本"
		特殊:老IE才叫elem.innerText;//第一见到小三上位,反而所有的主流浏览器来将就了老IE

	3、*input.value:获取或设置单标签(input)的内容准备的
		获取:input.value
		设置:input.value="新值"

元素的属性:

	1、*获取属性值:
		核心DOMelem.getAttribute("属性名")

		HTML DOMelem.属性名;

	2、*设置属性值:
		核心DOMelem.setAttribute("属性名","属性值");

		HTML DOMelem.属性名="新值";

	3、删除属性值:
		*核心DOMelem.removeAttribute("属性名")

		HTML DOMelem.属性名="" - 虽然简单,但是有的情况会删不干净,有的属性删不干净依然会有功能比如:href

	4、判断有没有 - 垃圾
		核心DOMelem.hasAttribute("属性名");

		HTML DOMelem.属性名!="";

		返回的结果是一个布尔值,只能判断有没有,不能判断是什么

	HTML DOM:有两个小缺陷:
		1class需要写为className
		2、一切自定属性不能操作
		3、删除删不干净,依然会留下属性节点
                

元素的样式:

	1、内联样式:
		获取:elem.style.css属性名
		设置:elem.style.css属性名="css属性值"
		特殊:
			1、css属性名如果有横线要省略,变为小驼峰命名法
			2、获取的时候只能获取到内联样式,这个小缺陷可以忽略不计

	2、样式表: - 不推荐
			//获取到你想要操作的某个样式表
			var sheet=document.styleSheets[i];
			//获取样式表中所有的样式规则
			var rules=sheet.cssRules;
			//选出自己想要操作的某个规则
			var rule=rules[i];
			//操作
			获取:console.log(rule.style.css属性名);
			设置:rule.style.css属性名="css属性值"

	为什么更推荐内联:
		1、不会牵一发动全身
		2、优先级一定是最高的

创建元素&渲染页面:3步

	1、先创建空标签
		var elem=document.createElement("标签名");
		
	2、为其添加必要属性和事件
		elem.属性名="属性值";
		elem.on事件名=function(){操作}

	3、渲染DOM树/页面:3种
	                *1、父元素.appendChild(elem);//elem追加到父元素里面,当最后一个儿子
		2、父元素.insertBefore(elem,已有子元素);//elem追加到父元素里面,插入在已有子元素的前面 - 影响其他元素的下标,不推荐
		3、父元素.replaceChild(elem,已有子元素);//elem追加到父元素里面,新元素替换掉已有子元素 - 不推荐
                

删除元素:elem.remove();

HTML DOM:简化核心DOM开发,核心语法太繁琐,提供了一些常用的对象

image对象

  • 仅仅只是简化了创建部分
  • 创建:var img=new Image(); - 不是人人都可以简化为构造函数创建方式

form对象

  • 仅仅只是简化了查找部分
  • 查找form元素:var form=document.forms[i];
  • 以及找表单控件:var inp=form.elements[i];

select对象:牛逼:提供了2个属性,2个方法,1个事件

属性:

  1. select.options === select.children; 获取select里面的所有的option
  2. *select.selectedIndex - 获取当前选中项的下标,一定是搭配联动一起使用

方法:

  1. *sel.add(option); - 完全相当于appendChild
  2. elem.remove(i); - 当时当remove删除元素出现过后,他就当场淘汰了

专属事件:

onchange - 选中项发生了变化才会触发

option对象:仅仅只是简化了创建部分

创建:var opt=new Option("innerHTML","value")

		一句话完成4个操作:sel.add(new Option("榴莲","榴莲"));
			1、创建了空的option	
			2、为option设置了innerHTML
			3、为option设置了value
			4、上树