页面逻辑处理
页面逻辑处理
BOM
浏览器对象模型(Browser Object Mode),js和浏览器交互的工具。
基本的架构如下:

可以看到window是所有对象的根。
window对象
描述浏览器窗口,也是所有对象的根。
所有全局变量,全局定义的函数,都被设置成window的成员(除了let定义的变量)。
a="i am a";
var b="i am b";
let c="i am c"; // c不是windows的属性
console.log(a);
console.log(b);
console.log(c);
console.log(window.a);
console.log(window.b);
console.log(window.c);
i am a
i am b
i am c
i am a
i am b
undefined
反过来,所有window的成员也是可以直接访问的:
console.log(window.document === document);
true
一些方法和属性:
属性 | 描述 |
---|---|
innerHeight | 窗口的内部高度,注意这个尺寸跟缩放比例有关 |
innerWidth | 窗口的内部宽度,注意这个尺寸跟缩放比例有关 |
outerHeight | 窗口的外部高度,包括滚动条和工具栏 |
outerWidth | 窗口的外部宽度,包括滚动条和工具栏 |
pageXOffset | 当前页面的滚动位置x |
pageYOffset | 当前页面的滚动位置y |
方法 | 描述 |
---|---|
open(url) | 打开地址是url的一个新窗口 |
close() | 关闭一个窗口,窗口必须是open打开的 |
stop() | 停止载入页面 |
scrollTo() | 滚动到指定坐标 |
具体可以看这里。 |
几类对象的作用
对象 | 作用 | 详细 |
---|---|---|
document | 文档对象,用来描述页面的内容,最常用 | 详细 |
location | 当前URL的相关信息 | 详细 |
navigator | 浏览器和操作系统的相关信息 | 详细 |
screen | 浏览器所在屏幕的信息,比如分辨率,dpi | 详细 |
history | 当前窗口的浏览历史 | 详细 |
一些常用的属性:
对象 | 属性方法 | 描述 |
---|---|---|
location | href | 当前url地址 |
location | port | 当前的端口 |
location | reload() | 重载当前页面 |
navigator | appName | 浏览器名称 |
navigator | cookieEnabled | 是否启用的cookie |
navigator | platform | 操作系统 |
screen | Height | 高度,注意是整个屏幕的高度 |
screen | Width | 宽度,也是整个屏幕的宽度 |
screen | ||
screen | ||
window | devicePixelRatio | 屏幕的缩放倍率 |
DOM操作
获取元素
所谓DOM就是(Document Object Model)的缩写,整个文档是一个树状结构从document开始:
<html>
<head>
<title>文档标题</title>
</head>
<body>
<a href="#">我的链接</a>
<h1>我的标题</h1>
</body>
</html>
对应的文档结构如下图:

再复习下getElement家族四兄弟:
函数 | 作用 | 描述 |
---|---|---|
getElementsByTagName | 用tag名去搜索元素 | 例如input、div |
getElementsByClassName | 通过class去搜索 | class="xxx" |
getElementsByName | 通过input这类控件的name属性搜索 | name="xxx" |
getElementById | 通过id搜索 | id="xx",我是奸细! |
注意除了最后一个,其他函数返回的都是(伪)数组。因为他们通常都不唯一。而id是全页面仅有一个的,因此可能的话,应该尽量用id来获取。 |
注意,并不是只能从document上去调用这个函数
<body>
<div>
<h1></h1>
<span></span>
</div>
<script src="index.js"></script>
</body>
let div = document.getElementsByTagName("div")[0];
let span = div.getElementsByTagName("span")[0];
span.innerHTML = "Hello World!";
我们先获得div这个元素,然后再用div去获得元素,这是没问题的。
设置元素属性
我们已经知道可以直接通过js对象的属性来修改元素的属性,比如:
let tag_a = document.getElementsByTagName("a")[0];
tag_a.href="https://www.baidu.com";
此外你也可以通过setAttribute和getAttribute来设置对应的属性和写入对应的属性:
console.log(tag_a.getAttribute("href"));
tag_a.setAttribute("href", "https://cn.bing.com");
显然这种方法没有直接用属性方便,但这种方式的可读性要好一些,因为读起来就知道这是在设置属性。
添加节点
你可以为元素添加节点,但这个操作需要两步:
// 之前的定义
//let div = document.getElementsByTagName("div")[0];
//tag_a = document.getElementsByTagName("a")[0];
let h3_head = document.createElement("h3");
h3_head.innerHTML = "头部插入";
div.insertBefore(h3_head, tag_a); // 在tag_a的前面插入h3_head
let h3_tail = document.createElement("h3");
h3_tail.innerHTML = "尾部插入";
div.appendChild(h3_tail); // 在div所有元素的最后插入h3_tail
创建节点
在插入节点之前,需要先创建节点。
document
的成员方法createElement
用来创建节点。创建的节点并不会立即被加入DOM树中,而是返回一个节点对象以供后面引用。
插入节点
我们用函数Element.insertBefore
和函数Element.appendChild
来将创建得到的节点插入到合适的位置。
Element.insertBefore(new_tag, existNode)
函数接受两个参数。函数会在节点existNode
前面插入new_tag
节点。这个函数必须传递两个参数,其中existNode
不可省。
Element.appendChild
函数只接受一个参数,也就是插入的节点,节点会被插入所有节点的最后。
删除节点
函数Element.removeChild
函数可以删除对应的节点
<div>
<h1>节点1</h1>
<h1>节点2</h1>
<h1>节点3</h1>
<h1>节点4</h1>
</div>
let removeH1 = function(){
let div = document.getElementsByTagName("div")[1];
let h1s = div.getElementsByTagName("h1");
div.removeChild(h1s[0]);
}
每次点击按钮,都可以将第一个h1删掉。
其他属性和操作
还有一些常用的Element属性,比如:
父节点
<div>
<a>这是一个链接</a>
<h1></h1>
<span></span>
</div>
//let tag_a = document.getElementsByTagName("a")[0];
console.log(tag_a.parentNode.nodeName);
DIV
parentNode
用来获得父节点
子节点
除了用getElement...系列函数来获得子节点之外,也可以直接访问他们:
属性 | 作用 |
---|---|
childNodes | 所有子节点,包括文本,属性和其他HTML子节点 |
children | 所有HTML节点 |
firstChild | 第一个子节点 |
lastChild | 最后一个子节点 |
兄弟节点
除了获取上下级节点之外,节点也能获取同级的其他节点。
注意我们的节点是处于一个数组之中的,你可以获得你周围的节点,上一个和下一个:
Element.previousElementSibling // Element的上一个节点
Element.nextElementSibling // Element的下一个节点
其他属性
我们已经学过innerHTML了,它就是内部的代码。除此之外innerText可以获得不包含HTML代码的纯文本内容,试试看:
console.log(document.getElementsByTagName("body")[0].innerHTML);
console.log(document.getElementsByTagName("body")[0].innerText);
nodeName属性可以获得节点的名称。
nodeType可以返回节点类型(1为元素节点,2为属性节点)。
style属性指向节点的css属性。
JavaScript的事件处理
例子
以下是一个简单的例子:
<h1 onclick="funcClick()">点击我</h1>
let funcClick = function(){
alert("点击成功!");
}
在html上申明onclick,说明这个元素要处理鼠标的点击事件。一般来说,我们会将这个事件绑定到某个函数上,本例里就是funcClick
。当tag被点击,onclick事件被触发,函数funcClick
被调用,完成弹窗。
我们把funcClick
这种函数称为回调函数。
窗口事件
窗口事件是一类非直接交互事件的统称,他们跟下面键盘或者鼠标事件不一样,没有明确的触发机制,因此不太好分类。
onload
onload事件在页面或者某个元素被加载完毕之后调用。当你赋值window.onload属性时,它会在页面加载之后调用。
这种用法的优点是显而易见的。你可以避免出现页面没有加载完成代码就被启动的情况。
onload也可以用在某个元素上,这样当某个元素被加载之后,函数就会被触发。
onresize和onscroll
这两个消息由窗口消息触发。
当窗口的尺寸被调整时,会触发onresize函数,当窗口被滚动时(也就是说滚动条发生变化时),onscroll会被触发。
window.onresize = function(){
let size = window.innerWidth.toString();
size += "x";
size += window.innerHeight.toString();
console.log("resize to "+size);
}
window.onscroll = function(){
let pos = window.pageXOffset.toString();
pos += "x";
pos += window.pageYOffset.toString();
console.log("scroll to "+pos);
}
窗口尺寸或者滚动条发生变化,就会触发这两个函数,在console窗口打印出调整后的结果。
焦点事件onblur和onfocus
简单理解,当你点入一个输入框时,可以进行文字输入时,这个输入框就获得焦点。反之当你点击其他位置,无法再在框里进行输入时,我们就说这个输入框失去了焦点。当控件获得焦点时,onfocus事件被触发,反之丢失时,onblur被触发。
有时候你可能需要实时检查用户的输入是否合法(邮箱是否合法,密码是否有足够的强度等)。这两个事件将很有用,你可以根据焦点状态判断是否要切入合法性检查判断。
鼠标事件
onclick、ondbclick
onclick我们已经见过了。ondbclick顾名思义,就是双击事件。
要注意的是,事件回调函数,都可以接收一个event参数,但这个参数在鼠标和键盘事件中,才会限的比较有用:
<h1 onclick="funcClickOne(event)">点击我</h1>
let funcClickOne = function(e){
let pos = e.clientX.toString() + "," + e.clientY.toString();
alert("点击成功!位置:"+pos);
}
注意html里的写法,传入的参数必须是event。
event是一个对象,里面放置了点击时的一些环境参数,比如clientX和clientY,就是点击时鼠标的位置(相对于窗口区的坐标,不是绝对坐标)。
详细内容看这里。
onmouseover、onmouseout
这两个事件在鼠标移入或者移出元素时触发,这是很常用的两个事件。
比如弹出式菜单,当鼠标悬停时,弹出多余的菜单选项。
onmousedown onmousemove onmouseup
这三个事件分别对应鼠标左键按下,鼠标移动和鼠标左键放开。
你可以用这三个事件来处理鼠标的拖拽操作。
键盘事件
onkeydown、onkeyup和onkeypress
onkeydown和onkeyup很好理解,某个键被按下和放开。要注意的是,如果你一直按某个键,那么onkeydown会一直被触发。onkeyup只在放开时触发一次。
onkeypress和onkeydown效果一样,不同的是这个消息只对字符键起作用,其他键(例如Ctrl,Shift等功能键)不起作用。
键盘事件要通过event来获得更多信息。比如哪个键被按下。event.keyCode放置按键的ascii码。具体看这里。