跳至主要內容

页面逻辑处理

xmut-lby大约 8 分钟

页面逻辑处理

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()滚动到指定坐标
具体可以看这里open in new window

几类对象的作用

对象作用详细
document文档对象,用来描述页面的内容,最常用详细open in new window
location当前URL的相关信息详细open in new window
navigator浏览器和操作系统的相关信息详细open in new window
screen浏览器所在屏幕的信息,比如分辨率,dpi详细open in new window
history当前窗口的浏览历史详细open in new window

一些常用的属性:

对象属性方法描述
locationhref当前url地址
locationport当前的端口
locationreload()重载当前页面
navigatorappName浏览器名称
navigatorcookieEnabled是否启用的cookie
navigatorplatform操作系统
screenHeight高度,注意是整个屏幕的高度
screenWidth宽度,也是整个屏幕的宽度
screendeviceXDPIx方向的dpi
screendeviceYDPIy方向的dpi
windowdevicePixelRatio屏幕的缩放倍率

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,就是点击时鼠标的位置(相对于窗口区的坐标,不是绝对坐标)。

详细内容看这里open in new window

onmouseover、onmouseout

这两个事件在鼠标移入或者移出元素时触发,这是很常用的两个事件。

比如弹出式菜单,当鼠标悬停时,弹出多余的菜单选项。

onmousedown onmousemove onmouseup

这三个事件分别对应鼠标左键按下,鼠标移动和鼠标左键放开。

你可以用这三个事件来处理鼠标的拖拽操作。

键盘事件

onkeydown、onkeyup和onkeypress

onkeydown和onkeyup很好理解,某个键被按下和放开。要注意的是,如果你一直按某个键,那么onkeydown会一直被触发。onkeyup只在放开时触发一次。

onkeypress和onkeydown效果一样,不同的是这个消息只对字符键起作用,其他键(例如Ctrl,Shift等功能键)不起作用。

键盘事件要通过event来获得更多信息。比如哪个键被按下。event.keyCode放置按键的ascii码。具体看这里open in new window