DOM 和 BOM 是浏览器提供的一套操作浏览器功能和页面元素的结构(API),结合事件可以方便的实现网页的动态效果。

事件三要素:

  1. 事件源(谁):触发事件的元素
  2. 事件类型(什么事件): 例如 click 点击事件
  3. 事件处理程序(做啥):事件触发后要执行的代码(函数形式),事件处理函数

DOM(Document Object Model)

获取元素

  • 根据ID获取元素对象:document.getElementById(id)
  • 根据标签名获取元素对象数组:document.getElementsByTagName(‘标签名’) 或者 element.getElementsByTagName(‘标签名’)
  • HTML5新增获取方式:document.querySelector(‘选择器’)或document.querySelectorAll(‘选择器’)
  • 获取特殊元素:document.body、document.documentElement

执行事件过程

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值方式)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <body>
    <button id="btn">唐伯虎</button>
    <script>
    // 点击一个按钮,弹出对话框
    // 1. 事件是有三部分组成 事件源 事件类型 事件处理程序 我们也称为事件三要素
    //(1) 事件源 事件被触发的对象 谁 按钮
    var btn = document.getElementById('btn');
    //(2) 事件类型 如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
    //(3) 事件处理程序 通过一个函数赋值的方式 完成
    btn.onclick = function () {
    alert('点秋香');
    };
    </script>
    </body>

常见的鼠标事件

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

常见的键盘事件

键盘事件触发条件
onkeyup某个键盘按键被松开时触发
onkeydown某个键盘按键被按下时触发
onkeypress某个键盘按键被按下时并弹起时触发

注意: onkeypress 和前面两个的区别是,它不识别功能键,比如左右箭头、shift 等

操作元素

以下操作中的element均指获取到的元素。

改变元素内容

  • element.innerText // 从起始位置到终止位置的内容, 但它去除 html 标签,同时空格和换行也会去掉
  • element.innerHTML // 起始位置到终止位置的全部内容,包括 html 标签, 同时保留空格和换行

改变常用属性

  1. 常用元素属性
  • element.src
  • element.href
  • element.id、element.alt、element.title
  1. 表单元素属性
  • element.type
  • element.value

值为bool型:

  • element.checked
  • element.selected
  • element.disabled

改变样式

  1. 操作 style 属性,常用于改变较少的样式。通过 element.style.”样式属性”,产生的是行内样式,CSS 权重比较高。

例子:显示隐藏文本框内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<body>
<input type="text" value="手机" style="color: #999" />
<script>
// 1.获取元素
var text = document.querySelector('input');
// 2.注册事件 获得焦点事件 onfocus
text.onfocus = function () {
// console.log('得到了焦点');
if (this.value === '手机') {
this.value = '';
}
// 获得焦点需要把文本框里面的文字颜色变黑
this.style.color = '#333';
};
// 3. 注册事件 失去焦点事件 onblur
text.onblur = function () {
// console.log('失去了焦点');
if (this.value === '') {
this.value = '手机';
}
// 失去焦点需要把文本框里面的文字颜色变浅色
this.style.color = '#999';
};
</script>
</body>
  1. 操作 className 属性,常用于更改较多样式的情况。通过 element.className 操作。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<head>
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
}

.change {
background-color: purple;
color: #fff;
font-size: 25px;
margin-top: 100px;
}
</style>
</head>

<body>
<div class="first">文本</div>
<script>
// 1. 使用 element.style 获得修改元素样式 如果样式比较少 或者 功能简单的情况下使用
var test = document.querySelector('div');
test.onclick = function () {
// this.style.backgroundColor = 'purple';
// this.style.color = '#fff';
// this.style.fontSize = '25px';
// this.style.marginTop = '100px';
// 让我们当前元素的类名改为了 change

// 2. 我们可以通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
// 3. 如果想要保留原先的类名,我们可以这么做 多类名选择器
// this.className = 'change';
this.className = 'first change';
this.className += ' change';
};
</script>
</body>

排他思想

对于同一组元素,想要每次操作其中一个元素,而其它元素不变,可以使用排他思想。

例子:按钮点亮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
// 1. 获取所有按钮元素
var btns = document.getElementsByTagName('button');
// btns得到的是伪数组 里面的每一个元素 btns[i]
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
// (1) 我们先把所有的按钮背景颜色去掉 干掉所有人
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = '';
}
// (2) 然后才让当前的元素背景颜色为pink 留下我自己
this.style.backgroundColor = 'pink';
};
}
//2. 首先先排除其他人,然后才设置自己的样式 这种排除其他人的思想我们成为排他思想
</script>
</body>

自定义属性

  • 获取属性值: element.getAttribute(‘属性’) //主要获得自定义的属性
  • 设置属性值: element.setAttribute(‘属性’, ‘值’); //主要设置自定义的属性
  • 移除属性值: element.removeAttribute(‘属性’);

HTML5推荐自定义属性以data-开头作为属性名并且赋值, 比如 <div data-index = “1”></div>,HTML5 新增 element.dataset.index 或者 element.dataset[‘index’] 来获取和设置这样的自定义属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
// console.log(div.getTime);
console.log(div.getAttribute('getTime'));
div.setAttribute('data-time', 20);
console.log(div.getAttribute('data-index'));
console.log(div.getAttribute('data-list-name'));
// h5新增的获取自定义属性的方法 它只能获取data-开头的
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
</body>

节点操作

一般地,节点至少拥有nodeType、nodeName、nodeValue这三个基本属性。

  • 元素节点 nodeType 为 1
  • 属性节点 nodeType 为 2
  • 文本节点 nodeType 为 3(文本节点包含文字、空格、换行等)

    一般我们只用元素节点,故下面的 node 也可以直接理解为上文中的 element 。

父节点

node.parentNode: 可返回某节点的父节点,注意是最近的一个父节点

子节点

parentNode.children: 返回所有的子元素节点,其余节点不返回

获取第一个子元素节点和最后一个子元素节点一般用以下方法:

  1. 第一个子元素节点:parentNode.children[0]
  2. 最后一个子元素节点:parentNode.children[parentNode.children.length - 1]

兄弟节点

node.nextElementSibling: 返回当前元素的下一个兄弟元素节点
node.previousElementSibling: 返回当前元素的上一个兄弟元素节点

创建、添加、删除、复制

  • 创建: document.createElement(‘tagName’)
  • 添加:
    1. node.appendChild(child) (将一个节点添加到指定父节点的子节点列表末尾)
    2. node.insertBefore(child, 指定元素节点) (将一个节点添加到父节点的指定子节点前面)
  • 删除: node.removeChild(child)(从 DOM 中删除一个子节点,并返回删除的节点(阻止链接跳转需要添加 javascript:void(0); 或者 javascript:;)
  • 复制: node.cloneNode()
    1. 如果括号中参数为空或者为 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
    2. 如果括号中参数为 true,则是深拷贝,会复制节点本身以及里面所有的节点

通过事件监听方法来注册事件

  • 传统注册方式:
    利用 on 开头的时间 onclick 、同一元素同一个事件只能设置一个函数
  • 事件监听方法来注册事件:
    同一个元素同一个事件可以注册多个监听器,按注册顺序依次执行,可以控制捕获和冒泡的事件流规则(默认为冒泡)

element.addEventListener(type, listener{},useCapture)

  • type:事件类型字符串,比如 click、mouseover,注意这里不要带 on
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值,默认为 false(冒泡)

事件委托

不是每个子节点单独设置事件注册,而是事件注册设置在其父节点上,然后利用冒泡原理影响设置每个子节点

1
2
3
4
5
6
7
// 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
// alert('知否知否,点我应有弹框在手!');
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
});

事件对象

eventTarget.onclick = function(event) {}
eventTarget.addEventListener(‘click’, function(event) {})
// 这个 event 就是事件对象,我们还喜欢写成 e 或者 evt

这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参进去,e.target 和 this 的区别:

  • this 是事件绑定的元素,这个函数的调用者(绑定这个事件的元素)
  • e.target 是事件触发的元素
事件对象属性说明
e.target返回触发事件的对象(标准)
e.type返回事件的类型,比如 click、mouseover(不带 on)
e.preventDefault()阻止默认事件(标准 比如不让链接跳转)
e.stopPropagation()阻止冒泡(标准)

例子:利用键盘时间对象的keyCode属性(返回该键的 ASCII 值
)检测用户是否按下了s 键,如果按下s 键,就把光标定位到搜索框里面

1
2
3
4
5
6
7
8
9
10
// 核心思路: 检测用户是否按下了s 键,如果按下s 键,就把光标定位到搜索框里面
// 使用键盘事件对象里面的keyCode 判断用户按下的是否是s键
// 搜索框获得焦点: 使用 js 里面的 focus() 方法
var search = document.querySelector('input');
document.addEventListener('keyup', function (e) {
console.log(e.keyCode);
if (e.keyCode == 83) {
search.focus();
}
});

BOM(Browser Object Model)

DOM 把文档当做一个对象来看待,顶级对象是 document,BOM把浏览器当做一个对象来看待,顶级对象是 window,BOM比DOM的级别更高,可以理解为BOM里包含DOM。

窗口加载事件

  • window.onload = function() {};
  • window.addEventListener(“load”, function() {});
    有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为是等页面内容全部加载完毕再去执行处理函数

document.addEventListener(‘DOMContentLoaded’, function() {})

DOMContentLoaded 事件触发时,仅当 DOM 加载完成,不包括样式表,图片,flash 等。