资讯专栏INFORMATION COLUMN

前端知识点总结——DOM

Vultr / 1842人阅读

摘要:前端知识点总结什么是什么是专门操作网页内容的标准为什么统一不同浏览器操作网页内容的标准优点几乎所有浏览器兼容什么是网页中所有内容在内存中都是保存在一棵树形结构中网页中每项内容元素文本属性注释,都是树上的一个节点对象。

前端知识点总结——DOM 1.什么是DOM: Document Object Model

什么是: 专门操作网页内容的API标准——w3c
为什么: 统一不同浏览器操作网页内容的API标准
优点: 几乎所有浏览器100%兼容

2.DOM Tree:

什么是: 网页中所有内容在内存中都是保存在一棵树形结构中
网页中每项内容(元素,文本,属性,注释...),都是树上的一个节点对象。
唯一的树根节点: document
为什么: 树形结构是最好的保存上下级包含关系的结构

节点对象: Node
网页中每项内容都是DOM树上的一个节点对象:
所有节点都有的三个属性:
nodeType: 节点类型

何时: 只要判断节点的类型时
包括: 
  document  9
  element    1
  attribute   2
  text       3
问题: 无法进一步区分元素的标签名

nodeName: 节点名称

何时: 只要进一步判断元素的标签名时
    ——可代替nodeType
包括:
 document   #document
 element     全大写标签名
 attribute     属性名——不常用!
 text        #text

nodeValue: 节点值 ——不常用

 document  null
 element    null
 attribute   属性值
 text       文本内容
3.查找: 4种:

1.不需要查找可直接获得节点:
document.documentElement html
document.head head
document.body body
document.forms[id/i] form

2.按节点间关系查找:
何时: 如果已经获得一个节点了。想找周围节点时。
包括: 2种树:

节点树: 包含网页中所有内容的完整树结构
2大类关系:
1.父子: 4种:
elem.parentNode elem的父节点
elem.childNodes elem的直接子节点
elem.firstChild elem下的第一个直接子节点
elem.lastChild elem下的最后一个直接子节点
2.兄弟: 2种:
elem.previousSibling elem的前一个兄弟元素
elem.nextSibling elem的后一个兄弟元素
问题: 受看不见的空字符的干扰!

2.元素树: 仅包含元素节点的树结构
2大类关系:

父子: 4种:
elem.parentElement elem的父元素
elem.children elem的直接子元素
elem.firstElementChild elem下的第一个直接子元素
elem.lastElementChild elem下的最后一个直接子元素

2.兄弟: 2种:

elem.previousElementSibling  elem的前一个兄弟元素
elem.nextElementSibling      elem的后一个兄弟元素

今后只要用DOM操作网页内容,都用元素树
说明: 元素树不是一棵新树,其实只是节点树的一个子集

childNodes和children: 动态集合(live collection)
什么是: 不实际存储属性值,每次访问集合都重新查找DOM树
优: 首次查找,效率高! 因为不用返回完整的属性。
缺: 每次访问集合,都会重新查找DOM树,降低效率
遍历:
不好: for(var i=0;i 好: for(var i=0,len=children.length;i

遍历指定父元素下的所有后代元素: 2种:
1.递归: 2步:
1.定义函数仅遍历指定父元素下的所有直接子元素
2.对每个直接子节点调用和父节点完全相同的操作
深度优先: 当一个节点同时拥有子节点和兄弟节点时,总是优先遍历子节点。
所有子节点遍历完,才返回遍历兄弟节点。
2.循环: 2步:
1.定义迭代器:

 迭代器: 可以依次获得每个后代元素节点的 专门对象
 如何: 
  创建: var iterator=document.createNodeIterator(
    parent, NodeFilter.SHOW_ELEMENT, null, false
  );

2.循环调用迭代器,获得下一个节点对象:

 var curr=iterator.nextNode()
 内置深度优先遍历的算法
 如果curr返回null,说明遍历结束

3.按HTML查找: 4种:
1.按id查找:

var elem=document.getElementById("id")
返回值: 一个元素
  如果找不到返回null!
强调: 1. 只能在document上调用

2.按标签名查找:

var elems=parent.getElementsByTagName("标签名")
返回值: 多个元素的集合
  如果找不到返回空集合
强调: 1. 可在任意父元素上调用
     2. 不但找直接子元素,且在所有后代中查找

3.按name查找:

var elems=document.getElementsByName("name")
返回值: 多个元素的集合
  如果找不到返回空集合
强调: 只能在document上调用

4.按class查找:

var elems=parent.getElementsByClassName("class")
返回值: 多个元素的集合
  如果找不到返回空集合
强调: 1.可在任意父元素上调用
     2.不但找直接子元素,且在所有后代中查找
     3.只要元素的一个class名匹配,就能找到该元素
      强调: 返回的集合都是动态集合
      问题: 每次只能按一个条件查找
      当查找条件复杂时,步骤很繁琐
      解决: 用选择器查找:

4.用选择器查找:

1.仅查找一个符合条件的:

var elem=parent.querySelector("选择器")
返回值: 一个元素
  如果找不到,返回null

2.查找多个符合条件的元素:

var elems=parent.querySelectorAll("选择器")
返回值: 多个元素的集合
  如果找不到返回空集合
  返回非动态集合: 实际存储属性值,即使反复访问集合,
  也不会导致反复查找DOM树
强调: 1. 可在任何父元素上调用
     2. 选择器只要相对于当前父元素内部即可
     3. 选择器的兼容性,受制于当前浏览器的兼容性

鄙视: 按HTML查找和按选择器查找的差别:

1.返回值: 按HTML查找返回动态集合
          按选择器查找返回非动态集合
2.效率: 首次查找: 按HTML查找效率高
                 按选择器查找效率低
3.易用性: 按HTML查找繁琐
          按选择器查找简单

总结: 今后,只要一个条件即可找到想要的元素,首选按HTML查找

    只要查找条件复杂,都选按选择器查找

jQuery中就是这么选择的

5.修改:

内容: .innerHTML .textContent .value
属性: 3种:
1.HTML标准属性: 2种:
1.核心DOM: 最初的DOM API,要求支持所有结构化文档

  优: 几乎万能   缺: 繁琐
 获取属性节点: var attrNode=elem.attributes[i]
 获取属性值: attrNode.value
   其实可以一步: var value=elem.getAttribute("属性名")
 修改属性值: elem.setAttribute("属性名","值")
 移除属性: elem.removeAttribute("属性名")
 判断是否包含指定属性: elem.hasAttribute("属性名")

2.HTML DOM: 专门操作HTML内容的API

            对核心DOM 常用API的简化
 优: 简单   缺: 不是万能
 简化: HTML DOM提前将所有标准属性,封装在了元素对象上,可用.直接访问.
  比如:
    获取属性值: elem.属性名
    修改属性值: elem.属性名="值"
     移除属性: elem.属性名=""
     判断是否包含指定属性: elem.属性名!==""
 特例: class属性: 
   ES的对象中已经先入为主的包含了内部属性class,用来记录对象创建时的类型名。
   HTML的class属性就无法同时存在
 所以: DOM: html的class属性,更名为className

2.状态属性: disabled selected checked
1.不能用核心DOM修改: 因为值是bool类型
2.只能用HTML DOM,打.修改
3.自定义扩展属性:
何时: 2种:

 1. 在元素上保存自定义数据
 2. 代替其他选择器,用来查找元素绑定事件

如何: 2套:

 不能用HTML DOM访问, 因为不是标准属性,未被提前封装在DOM元素对象中
 1. 普通属性名+核心DOM
 2. HTML5: 
  定义属性时: data-属性名="值"
  获取或修改属性值: elem.dataset.属性名

固定用法: 用自定义扩展属性代替其它选择器,为元素绑定事件

 为什么: 
   id: 唯一
   class: 经常变化
   elem: 做一种效果,可能使用任何元素
 解决: 今后,只要给元素绑定事件时,都要先为元素添加自定义扩展属性,
 再用自定义扩展属性查找元素,绑定事件
  优: 没有个数限制, 不会受样式影响而变化,不受元素限制
 如何: 
  定义: data-属性名="值"
  查找: 只能用属性选择器查找:[data-属性名=值]
6.样式: 2种:

1.内联样式:

修改: elem.style.css属性名
 强调: 1. css属性名都要去横线变驼峰
      2.长度数值必须加px单位
获取: 
 问题: 不能用elem.style.css属性名
 原因: elem.style仅包含内联样式! 无法获得内部或外部样式表中的样式
 解决: 获取计算后的样式!
  计算后的样式: 最终应用到元素上的所有样式的集合
                且将相对值换算为绝对值
  何时: 只要获取样式时,都要获取计算后的样式
  如何: 2步:
    1. 获得计算后的style对象:
      var style=getComputedStyle(elem);
    2. 从style中获得css属性值
      var value=style.css属性值
  强调: getComputedStyle获得样式都是只读!

2.内部/外部: 3步:
1.获得样式表对象:

 var sheet=document.styleSheets[i];

2.获得样式表对象中的cssRule

 什么是cssRule: 样式表中每个{}就是一个cssRule
 如何获得: var rule=sheet.cssRules[i]

3.获得cssRule中的style对象的css属性

 var value=rule.style.css属性

问题: 用elem.style.css属性一句话只能修改一个css属性

 如果同时修改多个属性,代码会很繁琐

解决: 用class批量应用样式
如何: 2步:

在css中准备好各种class

用程序,在对应情况下,选择对应的class应用!

7.添加:

添加: 3步:

创建空元素
var a=document.createElement("a");

2.设置必要属性
a.href="http://tmooc.cn";
a.innerHTML="go to tmooc";
3.将新元素添加到DOM树:3种api:
parent.appendChild(a) 将a追加到指定父元素下末尾
parent.insertBefore(a, child) 将a插入到指定父元素下的现有子元素之前
parent.replaceChild(a, child) 用a替换指定父元素下的现有子元素

优化: 尽量减少操作DOM树的次数, 从而减少重排重绘
为什么:
HTML页面加载过程:
html -> DOM Tree

       ↓
      Render Tree -> ***layout -> paint
       ↑

css -> cssRules
如何:

如果同时添加父元素和子元素时,应先在内存中,将所有子元素添加到父元素中,
再最后一次性将父元素添加到页面上

8.删除:

优化: 尽量减少操作DOM树的次数
为什么: 减少重排重绘
如何: 2种:
1.如果同时添加父元素和子元素,则应该现在内存中,将子元素添加到父元素,再最后将父元素一次性整体添加到DOM Tree
2.如果父元素已经在页面上了,要添加多个平级子元素,则应该使用文档片段:

什么是文档片段: 内存中临时存储多个子元素的虚拟父元素
何时: 只要向网页中同时添加多个平级子元素时,都可用文档片段
如何: 3步:
 1.创建文档片段
 2.将子元素添加到文档片段
 3.将文档片段整体添加到DOM 树

删除: parent.removeChild(child)

通常: child.parentNode.removeChild(child)
9.HTML DOM常用对象:

Image: 创建: var img=new Image();

Select: 代表页面上一个select元素
属性:
.selectedIndex 获得当前select选中的option的下标位置
.value 获得select中选中的option的值

      如果选中的option没有value属性,则用innerHTML代替

.options 获得当前select下所有option的集合

 .options.length 获得select下所有option的个数
  .options.length=0

.length => .options.length

 清空所有option  .length=0

方法: .add(option) 追加一个option

    问题: .add不支持文档片段
  .remove(i) 移除i位置的option

Option: 代表select下一个option元素
创建: var opt=new Option(text,value)
属性: .text .value .index

Table: 代表一个table元素
管着行分组:
创建行分组: var thead=table.createTHead()

          var tbody=table.createTBody()
          var tfoot=table.createTFoot()

删除行分组: table.deleteTHead()

          table.deleteTFoot()

获取行分组: table.tHead table.tFoot table.tBodies[i]
行分组: 管着行:
添加行: var tr=行分组.insertRow(i)

   在i位置插入一个新行
   固定套路: 1. 在末尾追加新行: .insertRow()
            2. 在开头插入新行: .insertRow(0)

删除行: 行分组.deleteRow(i) ——不常用!

    问题: i要求是在当前行分组内的相对下标位置
         无法自动获得
    应换为: table.deleteRow(tr.rowIndex)
     tr.rowIndex可自动获得当前行在整个table内的位置

获取行: 行分组.rows[i]
行: 管着格
添加格: var td=tr.insertCell(i)

固定用法: 行末尾追加一个格: tr.insertCell()
说明: 只能创建td,不能创建th

删除格: tr.deleteCell(i)
获取格: tr.cells[i]

Form: 代表一个form元素
获取: var form=document.forms[i/id]
属性: .elements 获得表单中所有表单元素的集合

     .elements.length  获得表单中,表单元素的个数
   .length => .elements.length

方法: .submit() 代替submit按钮,在程序中实现手动提交表单

表单元素:
获取: form.elements[i/id/name]

    更简化: form.name

方法: .focus 让当前表单元素获得焦点

结语:觉得总结的还可以的话,点下赞咯,你们的鼓励是我前进的动力,谢谢各位老铁们!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93043.html

相关文章

  • 前端识点总结——JQ

    摘要:前端知识点总结什么是第三方的极简化的操作的函数库第三方下载极简化是操作的终极简化个方面增删改查事件绑定动画效果操作学习还是在学,只不过简化了函数库中都是函数,用函数来解决一切问题为什么使用操作的终极简化解决了大部分浏览器兼容性问题凡是让用的 前端知识点总结——JQ 1.什么是jQuery: jQuery: 第三方的极简化的DOM操作的函数库 第三方: 下载 极简化: 是DOM操作的...

    jayzou 评论0 收藏0
  • 2017 前端面试准备 - 收藏集 - 掘金

    摘要:最近遇到的前端面试题更新版前端掘金个人博客已上线,欢迎前去访问评论无媛无故的个人博客以下内容非本人原创,是整理后觉得更容易理解的版本,欢迎补充。 一道面试题引发的对 javascript 类型转换的思考 - 前端 - 掘金 最近群里有人发了下面这题:实现一个函数,运算结果可以满足如下预期结果: ... 收集 JavaScript 各种疑难杂症的问题集锦 - 前端 - 掘金 从原博客迁移...

    王晗 评论0 收藏0
  • 2017 前端面试准备 - 收藏集 - 掘金

    摘要:最近遇到的前端面试题更新版前端掘金个人博客已上线,欢迎前去访问评论无媛无故的个人博客以下内容非本人原创,是整理后觉得更容易理解的版本,欢迎补充。 一道面试题引发的对 javascript 类型转换的思考 - 前端 - 掘金 最近群里有人发了下面这题:实现一个函数,运算结果可以满足如下预期结果: ... 收集 JavaScript 各种疑难杂症的问题集锦 - 前端 - 掘金 从原博客迁移...

    xiaochao 评论0 收藏0
  • 2017 前端面试准备 - 收藏集 - 掘金

    摘要:最近遇到的前端面试题更新版前端掘金个人博客已上线,欢迎前去访问评论无媛无故的个人博客以下内容非本人原创,是整理后觉得更容易理解的版本,欢迎补充。 一道面试题引发的对 javascript 类型转换的思考 - 前端 - 掘金最近群里有人发了下面这题:实现一个函数,运算结果可以满足如下预期结果: ... 收集 JavaScript 各种疑难杂症的问题集锦 - 前端 - 掘金从原博客迁移过来...

    KitorinZero 评论0 收藏0
  • 前端性能优化常用总结

    摘要:前言对于前端的性能话题,从来都没有断绝过。作为一个前端开发者,性能是我们关注的指标。前端发展以来,优化方式,琳琅满目,有雅虎军规等。所以,接下来我会从三个方面就前端性能进行总结网络方面操作及渲染方面数据方面。 前言 对于前端的性能话题,从来都没有断绝过。因为这个东西没有最好,只有更好。而且往往也是业务的繁杂程度去决定优化程度的。作为一个前端开发者,性能是我们关注的指标。它直接影响着我们...

    oliverhuang 评论0 收藏0

发表评论

0条评论

Vultr

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<