[TOC]

BOM

认识 BOM

image.png

window

Window 全局对象

image.png

Window 窗口对象

image.png

window 常见的属性 和 方法

这里主要讲的是浏览器中的窗口对象。

// 1.常见的属性
console.log(window.screenX)
console.log(window.screenY)

window.addEventListener("scroll", () => {
  console.log(window.scrollX, window.scrollY)
})

console.log(window.outerHeight) // 整个浏览器高度
console.log(window.innerHeight) // 窗口文档高度

// 2.常见的方法
const scrollBtn = document.querySelector("#scroll")
scrollBtn.onclick = function() {
  // 1.scrollTo
  window.scrollTo({ top: 2000 })

  // 2.close
  window.close()

  // 3.open
  window.open("http://www.baidu.com", "_self")
}

// 3.常见的事件
window.onload = function() {
  console.log("window窗口加载完毕~")
}

window.onfocus = function() {
  console.log("window窗口获取焦点~")
}

window.onblur = function() {
  console.log("window窗口失去焦点~")
}

const hashChangeBtn = document.querySelector("#hashchange")
hashChangeBtn.onclick = function() {
  location.hash = "aaaa"
}
window.onhashchange = function() {
  console.log("hash发生了改变")
}

EventTarget

Window 继承自 EventTarget,所以会继承其中的属性和方法:主要是和事件相关。

  • addEventListener:注册某个事件类型以及事件处理函数;
  • removeEventListener:移除某个事件类型以及事件处理函数;
  • dispatchEvent:派发某个事件类型到EventTarget上;

默认事件介绍:https://developer.mozilla.org/zh-CN/docs/Web/Events

const clickHandler = () => {
  console.log("window发生了点击")
}

// 添加事件,并指定回调函数
window.addEventListener("click", clickHandler)
// 删除事件
window.removeEventListener("click", clickHandler)

// 除了默认事件,也可以自定义的事件
window.dispatchEvent(new Event("hhh"))
// 监听自定义的事件
window.addEventListener("hhh", () => {
  console.log("监听到了hhh事件")
})

location

常见的属性

Location 对象用于表示 window 上当前链接到的 URL 信息。
常见属性:

  • href: 当前 window 对应的超链接URL, 整个URL;
  • protocol: 当前的协议;
  • host: 主机地址;
  • hostname: 主机地址(不带端口);
  • port: 端口;
  • pathname: 路径;
  • search: 查询字符串;
  • hash: 哈希值;
  • username:URL中的username(很多浏览器已经禁用);
  • password:URL中的password(很多浏览器已经禁用);

    常见的方法

    location 其实是 URL 的一个抽象实现。一个完整的 URL 的:
    image.png
    常用方法:

  • assign:赋值一个新的URL,并且跳转到该URL中;

  • replace:打开一个新的URL,并且跳转到该URL中(不同的是不会在浏览记录中留下之前的记录);
  • reload:重新加载页面,可以传入一个Boolean类型;

    history

    history 对象允许我们访问浏览器曾经的会话历史记录。

    常用属性和方法

    两个属性:

  • length:会话中的记录条数;

  • state:当前保留的状态值;

有五个方法:

  • back():返回上一页,等价于history.go(-1);
  • forward():前进下一页,等价于history.go(1);
  • go():加载历史中的某一页;
  • pushState():打开一个指定的地址;
  • replaceState():打开一个新的地址,并且使用replace;

image.png

DOM

认识 DOM 和整体架构

image.png
浏览器是用来展示网页的,而网页中最重要的就是里面各种的标签元素,JavaScript很多时候是需要操作这些元素的。

  • JavaScript如何操作元素呢?通过 Document Object Model(DOM,文档对象模型)。
  • DOM 给我们提供了一系列的模型和对象,让我们可以方便的来操作 Web 页面。

    EventTarget

    从整体架构中可以看到 EventTarget 是所有对象的爹,所以 EventTarget 中处理事件的函数,文档对象 document 都有。 ```javascript document.addEventListener(“click”, () => { console.log(“document被点击”) })

const divEl = document.querySelector(“#box”) const spanEl = document.querySelector(“.content”)

divEl.addEventListener(“click”, () => { console.log(“div元素被点击”) })

spanEl.addEventListener(“click”, () => { console.log(“span元素被点击”) })

<a name="TzGNb"></a>
## Node 节点
一个页面中有标签元素,有文本,有注释等等,它们各有不同,也有很多一致的地方,将这些共同点抽象出来就形式了 Node 节点接口。

- [https://developer.mozilla.org/zh-CN/docs/Web/API/Node](https://developer.mozilla.org/zh-CN/docs/Web/API/Node)

Node 有几个非常重要的属性:

- `nodeName`:node节点的名称。
- `nodeType`:可以区分节点的类型。
- `nodeValue`:node节点的值;
- `childNodes`:所有的子节点;
<a name="L417h"></a>
## Document
Document 节点表示整个载入的网页,它拥有网页中的一切。整体上可以细分为 HTML网页和 XML 网页。<br />常见的属性:

- title:文档标题
- body、head:放回 body 和 head 节点、
- children:返回整个 html 页面数组,索引为 0 ,表示整个页面的标签元素节点
- location:url 也是页面的一部分,所以 document 也能拿到,并且和 BOM 中的 location 一模一样

常见方法:

- `createElement()`:创建元素标签
- `appendChild()`:添加子节点,document 对象中有这个方法,但是浏览器做了限制,不能直接调用
   - 所以一般是通过一个更下层的标签元素来调用`document.body.addpendChild()`
- `removeChild()`:删除节点
- `getElementById()`
- `getElementsByName()`
- `getElementsByTagName()`
- `querySelector()`
- `querySelectorAll()`
```javascript
// 常见的属性
console.log(document.body)
console.log(document.title)
document.title = "Hello World"

// console.log(document.head)
console.log(document.children)

console.log(window.location)
console.log(document.location)
console.log(window.location === document.location) // true

// 常见的方法
// 创建元素
const imageEl = document.createElement("img")
const imageEl2 = new HTMLImageElement()

// 获取元素
const divEl1 = document.getElementById("box")
const divEl2 = document.getElementsByTagName("div")
const divEl3 = document.getElementsByName("title")
const divEl4 = document.querySelector(".content")
const divEl5 = document.querySelectorAll(".content")

Element

我们平时创建的 div、p、span 等元素在DOM中表示为 Element 元素。

const divEl = document.querySelector("#box")

// 常见的属性
console.log(divEl.id) // id
console.log(divEl.tagName) // 标签名
console.log(divEl.children) // 该元素下所有节点构成的数组
console.log(divEl.className) // 以字符串的形式返回 class
console.log(divEl.classList) // 以数组的形式返回 class

// 特有的常见方法:
// 获取属性的值
const value = divEl.getAttribute("age")
console.log(value)
// 设置属性的值
divEl.setAttribute("height", 1.88)

还有一些边界值的属性:
26. BOM、DOM、浏览器事件 - 图7

事件

事件监听

image.png
三种事件监听方式:

  1. 在script中直接监听
  2. 通过元素的on来监听事件
  3. 通过 EventTarget 中的addEventListener来监听(dom3 中提出)
    <!-- 基本被弃用 -->
    <button onclick="console.log('hhh')"></button>
    
    <!-- 在标签中执行表达式 -->
    <button onclick="h()"></button>
    <script>
    function h() {
     console.log('hhh');
    }
    </script>
    <!-- 一般是获取元素后绑定事件 -->
    <button id="btn"></button>
    <script>
    const btn = document.querySelector('#btn')
    btn.onclick = function () {
     console.log('hhh');
    }
    // 存在一个缺点,这样绑定相当于给元素添加了属性,而属性间存在覆盖
    btn.onclick = function () {
     console.log('666'); // 覆盖了hhh
    }
    </script>
    
    <!-- 推荐使用,不存在覆盖问题 -->
    <button id="btn1"></button>
    <script>
    const btn1 = document.querySelector('#btn1')
    btn1.addEventListener('click', () => {
     console.log('hhh');
    })
    </script>
    

    认识事件流的由来

    事实上对于事件有一个概念叫做事件流,为什么会产生事件流呢?
  • 我们可以想到一个问题:当我们在浏览器上对着一个元素点击时,你点击的不仅仅是这个元素本身;
  • 这是因为我们的 HTML 元素是存在父子元素叠加层级的;

比如一个span元素是放在div元素上的,div元素是放在body元素上的,body元素是放在html元素上,就像 ps 中的图层概念一样。
因为存在层级的概念,所以触发某层级的事件,也会相应的触发其他层级的相同事件。

事件冒泡和事件捕获

事件传递是有顺序的

  • 事件冒泡(Event Bubble):内层触发事件,当前层级回调函数执行,事件像泡泡一样往上层层触发
  • 事件捕获(Event Capture):内层触发事件,最外层级回调函数执行,然后事件一层一层往下被捕获触发

默认为事件冒泡,addEventListener(事件, 回调, true)第三个参数为 true 时,该事件流变成事件捕获,当内层事件发生,该事件将会被触发。
如果同时有事件冒泡和事件捕获的监听,那么会优先监听到事件捕获。

<body>
  <div>
    <p></p>
  </div>
</body>

<script>
  document.querySelector('p').addEventListener('click', () => {
    console.log('p 点击事件被触发了');
  })
  document.querySelector('div').addEventListener('click', () => {
    console.log('div 点击事件被触发了');
  })
  document.querySelector('body').addEventListener('click', () => {
    console.log('body 点击事件被触发了');
  })
</script>

<!-- 点击 p 标签,默认为事件冒泡,从内层向外层传递 -->
<!-- 
p 点击事件被触发了
div 点击事件被触发了
body 点击事件被触发了 -->
<!-- addEventListener 第三个参数为 true,则为事件捕获 -->
<script>
  document.querySelector('p').addEventListener('click', () => {
    console.log('p 点击事件被触发了');
  }, true)
  document.querySelector('div').addEventListener('click', () => {
    console.log('div 点击事件被触发了');
  }) // 事件冒泡
  document.body.addEventListener('click', () => {
    console.log('body 点击事件被触发了');
  }, true)
</script>

<!-- 事件捕获,点击 p 标签,最外层 body 触发事件,div 元素事件流不为事件捕获,则跳过
直接到最里层级 p 触发事件,然后再默认事件冒泡,div 元素触发事件 -->
<!-- 
body 点击事件被触发了
p 点击事件被触发了
div 点击事件被触发了-->

为什么会产生两种不同的处理流呢?

  • 这是因为早期浏览器开发时,不管是IE还是Netscape公司都发现了这个问题,但是他们采用了完全相反的事件流来对事件进行了传递;
  • IE 采用了事件冒泡的方式,Netscape 采用了事件捕获的方式;

    事件对象 event

    当一个事件发生时,就会有和这个事件相关的很多信息:

  • 比如事件的类型是什么,你点击的是哪一个元素,点击的位置是哪里等等相关的信息;

  • 那么这些信息会被封装到一个Event对象中;
  • 该对象给我们提供了想要的一些属性,以及可以通过该对象进行某些操作;

常见的属性:

  • type:事件的类型;
  • target:当前事件发生的元素;
  • currentTarget:当前处理事件的元素;
  • offsetX、offsetY:点击元素的像素位置;

比如点击事件中,target 就是被点击的那个元素,它是不变的。currentTarget 是当前响应点击事件而执行处理函数的元素,所以这个元素是随着事件流捕获或者冒泡在变化。

常见的方法:

  • preventDefault:取消事件的默认行为;
  • stopPropagation:阻止事件的进一步传递,当前元素还是会触发事件,只是不再传递下去;
    • Propagation:繁殖。阻止事件繁殖 ```html

      百度

```