JavaScript-DOM和BOM学习笔记——持续更新

本篇整理了一下DOM的一些基础知识,目前记录的知识还比较基础,更深的知识尚未整理。往后将继续学习和补充。
如有记录得不对的地方,欢迎探讨。

目录

  • DOM
    • DOM操作
      • 元素操作
        • 创建元素
        • 添加节点
        • 删除元素
        • 修改元素
        • 获取元素
      • 属性操作
      • 事件操作
        • 事件的三要素
        • 事件注册
        • 删除事件(解绑事件)
        • 事件类型
        • DOM事件流
        • 事件对象
        • 事件委托
  • BOM
    • window对象的常见事件
      • 1 窗口加载事件load
      • 2 窗口加载事件DOMContentLoaded
      • 3 调整窗口大小事件resize
    • 定时器
      • setTimeout()
      • setInterval()
    • location对象
      • 属性
      • 方法
    • navigator对象
    • history对象
    • screen对象

DOM

文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。

  • 我们获取过来的DOM元素是一个对象(Object),所以称为文档对象模型
  • 顶级对象是document

DOM操作

元素操作

元素操作主要有创建、增、删、改、查

创建元素

  • document.write():如果页面文档流加载完毕再调用它,会导致页面重绘;(实际开发中不常用)

  • innerHTML:是将内容写入某个DOM节点,不会导致页面重绘;

  • createElement:不会导致页面重绘;

    • 在页面中添加一个元素,往往需要两步:
      1. 创建节点:document.createElement(‘node’);
      2. 添加节点:node.appendChild 或 node.insertBefore
  • 经典面试题:innerHTML 和 createElement 的效率哪一个更高?

  • innerHTML创建多个元素效率更高(不要以拼接字符串的方式,以数组存储字符串(push),再填入innerHTML(join))

  • createElement 创建多个元素的效率稍微低一点,但是结构更为清晰。

添加节点

  • node.appendChild(child):后面追加元素

  • node.insertBefore(要插入的元素child, 指定元素):在指定元素前插入元素

  • node.cloneNode():

    • 括号为空或里面是false,则是浅拷贝,只复制节点本身,不复制里面的内容(子节点);
    • 括号里面为true,则是深拷贝。

删除元素

node.removeChild(child):删除一个子节点,返回删除的节点

修改元素

主要修改的是dom元素的属性,内容,表单的值,元素样式等。

  1. 修改元素属性:src、href、title等
  2. 修改普通元素内容:innerHTML、innerText
    • innerText
      • 不识别html标签
      • 读取时去除html标签,同时去除空格、换行
    • innerHTML
      • 识别html标签
      • 读取时包含html标签,同时保留空格、换行
  3. 修改表单元素:value、type、disabled等
    • 该注意的是修改和获取表单元素的值用value,而不是innerHTML
  4. 修改元素样式:style、className
    • style里面的属性采用驼峰写法
    • 通过修改style属性,为行内样式,CSS权重高
    • className会直接改变类名,覆盖原先的类名

获取元素

DOM提供的API:

  • getElementById():参数为字符串,需要加引号,找不到元素则返回null

  • getElementsByTagName()

  • getElementsByClassName()

H5提供的新方法:

  • querySelector()

  • querySelectorAll()

节点操作:

网页中所有内容都是节点(标签节点、属性节点、文本节点、注释节点等)

一般来说,节点至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)

  • nodeType

    元素节点:nodeType = 1;

    属性节点:nodeType = 2;

    文本节点:nodeType = 3;(包括文字、空格、换行)

  • 父级节点:node.parentNode

    • 得到的是离元素最近的父节点(是爸爸不是爷爷)
    • 若找不到,返回null
  • 子节点

    1. node.childNodes(标准)

      • 返回结果中包含元素节点、文本节点(如空格和换行)等

      • 若想只获得元素节点,可通过for循环+nodeType判断获得

    2. node.children(非标准)

      • 我们往往只想获取子元素节点,不需要你把换行这种文本节点都获取过来

      • 获取所有子元素节点(不包含文本节点),实际开发中常用

    3. node.firstChild 和 node.lastChild

      • 分别获取第一个子节点和最后一个子节点,包含元素节点、文本节点(如空格和换行)等
    4. node.firstElementChild 和 node.lastElementChild

      • 分别获取第一个子元素节点和最后一个子元素节点
    5. node.children[0] 和 node.children[node.children.length - 1]

      • node.firstElementChild 和 node.lastElementChild 的存在兼容性要求
      • 因此实际开发中,我们常用的是node.children[],以伪数组获取值的方式
  • 兄弟节点:

    • node.nextSibling:下一个兄弟节点

    • node.previousSibling:上一个兄弟节点

    显而易见,上面两种获取方式也是会将除元素节点之外的节点获取过来的,于是有了另外两种获取方式:

    • node.nextElementSibling:下一个兄弟元素节点
    • node.previousElementSibling:上一个兄弟元素节点

    不过后面两种同样存在兼容性要求,解决的思路是自行封装一个兼容性函数。

属性操作

  1. 获取属性

    • 获取内置属性:ele.Attr
    • 获取自定义属性(标准):ele.getAttribute(‘Attr’)
  2. 设置属性

    • ele.Attr = 'value’

    • ele.setAttribute(‘Attr’, ‘value’)

    • 需要注意的是修改类名的时候,两种方法对类名属性要求不同:

      • ele.className = 'newCLassName’
      • ele.setAttribute(‘class’, ‘newClassName’)

      这是由于在js中,class为保留字

  3. 移除属性

    • ele.removeAttribute(‘Attr’)
  4. 获取自定义属性

    • ele.getAttribute(‘data-attr’):兼容性好

    • ele.dataset.attr 或 ele.dataset[‘attr’]

      • dataset 是一个对象, 存放所有以data开头的自定义属性

      • dataset只能获取“data-”开头的属性

      • 如果自定义属性中有多个链接的单词,JS中采用驼峰命名法

事件操作

事件的三要素

  1. 事件源
  2. 事件类型
  3. 事件处理程序

事件注册

  1. 传统注册方式:

    ele.onclick = function(){}
    
    • 注册事件的唯一性:同一个元素同一个事件只可设置一个处理函数,后面注册的函数覆盖前面
  2. 事件监听方式:

    ele.addEventListener('click', function(){}, false)
    
    • 事件类型不带type
    • 注册事件没有唯一性:同一个元素同一个事件可添加多个监听器(事件处理程序)
  3. ie9以下:

    ele.attachEvent('onclick', function(){})
    

删除事件(解绑事件)

  1. 传统方式:

    e.onclick = null
    
  2. 事件监听:

    e.removeEventListener('click', fn)
    
  3. ie9以下:

    e.detachEvent('onclick', fn)
    

事件类型

  1. 常用的鼠标事件:

    鼠标事件 触发条件
    onclick 鼠标点击左键触发
    onmouseover 鼠标经过触发
    onmouseout 鼠标离开触发
    onfocus 获得鼠标焦点触发
    onblur 失去鼠标焦点触发
    onmousemove 鼠标移动触发
    onmouseup 鼠标弹起触发
    onmousedown 鼠标按下触发

    除此之外,还有一些常用的:

    • 禁止鼠标右键菜单:(主要用于程序员取消默认的上下文菜单)

      document.addEventListener('contextmenu', function(e) {
      	e.preventDefault();
      })
      
    • 禁止鼠标选中:

      document.addEventListener('selectstart', function(e) {
          e.preventDefault();
      })
      
  2. 常用的键盘事件:

    键盘事件 触发条件
    onkeyup 键盘弹起触发
    onkeydown 键盘按下触发
    onkeypress 键盘按下触发

    onkeydown 和 onkeypress 区别:

    • onkeypress不识别功能键,如ctrl、shift、上下左右箭头、删除键等
    • onkeydown 和 onkeyup 的 keyCode 不识别大小写,a 和 A 返回的 keyCode 相同;onkeypress 识别大小写

    事件调用顺序:keydown ---- keypress ---- keyup

DOM事件流

事件流描述的是从页面中接收事件的顺序。

事件发生时会在元素节点间按照特定的顺序传播,这个传播过程就是DOM事件流。

比如我们给一个div注册了事件,DOM事件流分为三个阶段:

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段

JavaScript-DOM和BOM学习笔记——持续更新_第1张图片

注意:

  1. JS代码中只可以执行捕获或冒泡其中一个阶段;
  2. onclick 和 attachEvent 只可以得到冒泡阶段;
  3. addEventListener 中:
    • 第三个参数如果是false(默认),表示在冒泡阶段调用事件处理程序
    • 第三个参数如果是true,表示在捕获阶段调用事件处理程序
  4. 有些事件没有冒泡,如:onfocus、onblur、onmouseenter、onmouseleave

事件对象

事件对象是事件的一系列信息数据的集合,与具体的事件有关

  • ie9以下只识别window.event,处理:

    e = e || window.event
    
  • e.target 和 this 的区别:

    • e.target 返回的是触发事件的对象/元素(点击了谁)

    • this 返回的是绑定事件的对象/元素

    如:

    <ul>
    	<li>1li>
    	<li>2li>
    	<li>3li>
    ul>
    

    给ul绑定click事件,但点击的是li,则:e.target 返回的是li,this返回ul

  • currentTarget用法与this一样,且有兼容性要求,因此不常用,用this就可以了

  • e.type返回事件类型

  • 阻止默认行为:e.preventDefault()

  • 阻止事件冒泡:e.stopPropagation()

  • 鼠标事件中:

    • e.clientX / e.clientY:鼠标在可视区域坐标
    • e.pageX / e.pageY:鼠标相对文档页面的坐标
    • e.screenX / e.screenY:鼠标相对屏幕坐标
  • 键盘事件中:keyCode可以获取按下键的ASCII值,可用于判断按下了什么键

事件委托

描述(面试):不是每个子节点单独设置事件监听器,而是把事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。




BOM

  • BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。

  • BOM把「浏览器」当做一个「对象」来看待

  • BOM 学习的是浏览器窗口交互的一些对象

  • BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差

  • BOM由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。

JavaScript-DOM和BOM学习笔记——持续更新_第2张图片

  • window对象是浏览器的顶级对象,它具有双重角色:

    • 它是JS访问浏览器窗口的一个接口

    • 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法

    在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等。

    注意:window下有个特殊的属性——window.name

window对象的常见事件

1 窗口加载事件load

window.onload = function() {}
window.addEventListener('load', function(){})

window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等),就调用的处理函数。

注意:

  1. 有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,再去执行处理函数。

  2. window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。

  3. 如果使用 addEventListener 则没有限制

2 窗口加载事件DOMContentLoaded

document.addEventListener('DOMContentLoaded', function(){})
  • DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。

  • Ie9以上才支持

  • 如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。

3 调整窗口大小事件resize

  • 只要窗口大小改变就触发

  • 我们经常利用这个事件完成响应式布局。可以通过 window.innerWidth 获取当前屏幕的宽度

定时器

setTimeout()

  • setTimeout执行函数的this指向window

  • 一般会给定时器添加标识符(方便后面清除):

    let timer = setTimeout(function() {
    	console.log(1)
    }, 1000)
    
  • 清除定时器:

    window.clearTimeout(timer)
    

    window可以省略

setInterval()

  • setInterval执行函数的this指向window

  • 一般会给定时器添加标识符(方便后面清除)

  • 清除定时器:

    window.clearInterval(timer)
    

    window可以省略

location对象

window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析 URL 。 因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。

属性

location对象属性 返回值
location.href 获取或设置整个URL
loaction.host 返回主机/域名
location.port 返回端口号,如果未写返回空字符串
location.pathname 返回路径
location.search 返回参数
location.hash 返回片段 #后面的内容

方法

location对象方法 返回值
location.assign() 和href一样,可以跳转页面(也称为重定向页面),有历史记录,可以返回和前进
location.replace() 替换当前页面,没有历史记录,不能返回和前进
location.reload() 刷新页面,可带参数false或true,默认为false,表示刷新,相当于F5;true表示强制刷新,相当于ctrl+F5

navigator对象

navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。

下面前端代码可以判断用户那个终端打开页面,实现跳转:

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
    window.location.href = "";     //手机
 } else {
    window.location.href = "";     //电脑
 }

history对象

history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面:

  • history.pushState()

    history.pushState({},'','/foo')
    
  • history.replaceState()

    history.replaceState({},'','/foo/bar')
    
  • history.go()

    history.go(-1)//后退一个页面
    history.go(1)//前进一个页面
    
  • history.back() 等价于 history.go(-1)

  • history.forward() 等价于 history.go(1)

screen对象

screen对象在编程中用处不大,基本上只用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等,每个浏览器的screen对象都包含着各不相同的属性。

你可能感兴趣的:(JavaScript-DOM和BOM学习笔记——持续更新)