BOM
认识 BOM
window
Window 全局对象
Window 窗口对象
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 的:
常用方法:assign
:赋值一个新的URL,并且跳转到该URL中;replace
:打开一个新的URL,并且跳转到该URL中(不同的是不会在浏览记录中留下之前的记录);reload
:重新加载页面,可以传入一个Boolean类型;history
常用属性和方法
两个属性:
length:会话中的记录条数;
- state:当前保留的状态值;
有五个方法:
back()
:返回上一页,等价于history.go(-1);forward()
:前进下一页,等价于history.go(1);go()
:加载历史中的某一页;pushState()
:打开一个指定的地址;replaceState()
:打开一个新的地址,并且使用replace;
DOM
认识 DOM 和整体架构
浏览器是用来展示网页的,而网页中最重要的就是里面各种的标签元素,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)
事件
事件监听
三种事件监听方式:
- 在script中直接监听
- 通过元素的on来监听事件
- 通过 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
- Propagation:繁殖。阻止事件繁殖
```html
```