BOM
是一个用于访问浏览器和计算机屏幕的对象集合。通过全局对象window来访问这些对象。
window.navigator 用于反映浏览器及其功能信息的对象
window.navigator.userAgent; 用于浏览器识别的长字符串
window.navigator.userAgent;
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
if(navigator.userAgent.indexOf('Firefox') !== -1){
console.log('这是火狐浏览器');
}
这是火狐浏览器
同时navigator也是控制台的备忘功能,其功能涵盖了BOM和DOM中所有的对象。
window.location 用于存储当前载入页面URL信息的对象
关于页面url操作由他操作,其本属性。
for(var i in window.location){
if(typeof location[i] === 'string'){
console.log(i+'="'+location[i]+'"');
}
}
href="https://www.mozilla.org/en-US/firefox/69.0a2/whatsnew/?oldversion=68.0" debugger eval code:3:13
origin="https://www.mozilla.org" debugger eval code:3:13
protocol="https:" debugger eval code:3:13
host="www.mozilla.org" debugger eval code:3:13
hostname="www.mozilla.org" debugger eval code:3:13
port="" debugger eval code:3:13
pathname="/en-US/firefox/69.0a2/whatsnew/" debugger eval code:3:13
search="?oldversion=68.0" debugger eval code:3:13
hash=""
通过修改href属性,可以直接实现页面的跳转。
location.href = 'http://www.baidu.com';
基本方法:
- reload() 与assign功能一样,不过它不会在浏览器的历史记录表中留下记录
- assign()
location.assign('http://www.baidu.com');
- reload() 重新载入这个页面
window.history 允许我们以有限的权限操作同一个浏览器会话中的已访问页面
window.history.length; //查看用户在这之前访问了多少页面,但为了隐私,无法查看访问的页面
2
history.forward(); //相当于在浏览器中单击前进按键
history.back(); //相当于在浏览器中单击后退按键
history.go(int); //0相当于重载该页面。负数相当于后退,正数相当于前进 history.go(2) 前进两条记录
history.pushState({a:1},"","hello");
undefined
history.pushState({a:2},"","hello-you-too");
window.screen 提供的是浏览器以外的环境信息(屏幕信息)
window.screen.colorDepth; //当前显示器的色位
24
window.screen.width; //浏览器的宽度
1366
screen.availWidth; //浏览器除去操作系统菜单的宽度
1366
screen.height; //浏览器的高度
768
screen.availHeight; //浏览器除去操作系统的有郊高度
728
window.devicePixelRatio; //设备物理像素与设备独立像素的比例
1
window.open()/close() 打开与关闭浏览器窗口
注意:目前多数浏览器会阻止浏览器的弹出窗
var a = window.open('http://www.packtpub.com','packt','resizable=yes,width=300,height=300');
undefined
a.close();
参数分别是:要载入新窗口的URL,新窗口的名字,resizable尺寸的可调整性,宽度,高度
window.alert(),window.prompt(),window.confirm()
var a = window.confirm('你是男生吗');
undefined
a //在弹出框单击ok后
true
var b = window.alert('只是一个警告');
undefined
var c = window.prompt('你的名字');
undefined
c //在弹出框输入zhu单击ok
"zhu"
var c = window.prompt('你的名字','提示'); //提示相当于默认值
window.setTimeout()、window.setInterval() 用于某些代码片段的执行调度
虽然我们指定执行时间,但其实并不是完全按照时间来的,和js机制有关,也就是它并不是完成准确的。
var a = 1;
undefined
var b = function(){
console.log('执行'+(a++)+'次');
}
undefined
window.setTimeout(b,1000); //设置b函数在1秒后执行1次
4
执行1次
window.setInterval(b,1000); //设置b函数每1秒执行1次
6
执行1次 2 debugger eval code:2:11
执行2次 2 debugger eval code:2:11
clearInterval(6); //结束6号进程
undefined
执行2次
DOM
下边的测试是在此html的控制器进行
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My page</title>
</head>
<body>
<p class="opener">first paragraph</p>
<p><em>second</em> paragraph</p>
<p id="closer">final</p>
<!--and that's about it'-->
</body>
</html>
每个节点都有属于自己的nodeType,nodeName和nodeValue属性
nodeType:1(元素类节点),2(属性类节点),3(文本类节点),9(文档类节点)
document.nodeType
9
document.nodeName;
"#document"
document.nodeValue;
null
HTML的根节点就是<html>标签,可以通过document对象的documentElement属性来访问他。
hasChildNodes() 判断有无子节点
document.documentElement.hasChildNodes();
true
document.documentElement.childNodes.length; //head,body以及两者之间的空白
3
parentNode 任何节点都可以通过此访问其父节点
document.documentElement.childNodes[2].parentNode;
<html>
length 判断节点数量
var bd = document.documentElement.childNodes[2]; //bd现在是body节点
undefined
bd.childNodes.length;
9
//3个p节点,1个注释节点。body与p之间的空白,p与p之间的空白,p与注释之间的空白,注释与body之间的空白。共5个。 3+1+5 = 9
<body>
<p class="opener">first paragraph</p>
<p><em>second</em> paragraph</p>
<p id="closer">final</p>
<!--and that's about it'-->
</body>
hasAttributes 判断有无属性
属性:class,id,name都称为属性
bd.childNodes[1];
<p class="opener">
bd.childNodes[1].hasAttributes();
true
bd.childNodes[1].attributes.length; //有一个属性,也就是class属性
1
可以通过索引值或属性名来访问一个属性
bd.childNodes[1].attributes[0].nodeName;
"class"
bd.childNodes[1].attributes[0].nodeType;
2
bd.childNodes[1].attributes[0].nodeValue;
"opener"
bd.childNodes[1].getAttribute('class');
"opener"
访问节点的内容,查看这个节点的输出
<p class="opener">first paragraph</p> 注意这个的结构是 p节点中包括text节点。text节点的nodeValue是first paragraph
bd.childNodes[3].innerHTML; //会把这个节点输出的html返回
"<em>second</em> paragraph"
bd.childNodes[3].textContent; //只返回标签字符串
"second paragraph"
bd.childNodes[3].childNodes.length;
2
bd.childNodes[3].childNodes[0].childNodes[0].nodeValue; //第一个childNodes[0]是em标签,第二个才是text标签
"second"
bd.childNodes[3].childNodes[1].nodeValue;
" paragraph"
DOM访问的快捷方式
通过childNodes,parentNode,nodeName,nodeValue及attributes这些属性,我们可以访问节点,不过因为空白处也是一个节点,只要页面发生一些细微的变化就可以导致js无法使用,当节点深度更深,我们将要写更多的代码。
getElementsByTagName()
以标签名(p标签,a标签等)为参数,返回当前HTML页面中所有匹配该标签名的节点集合
//查找第一个p标签下的第一个节点的值
document.documentElement.getElementsByTagName('p')[0].childNodes[0].nodeValue;
"first paragraph"
//查找第一个p标签的属性
document.documentElement.getElementsByTagName('p')[0].attributes[0];
class="opener"
document.documentElement.getElementsByTagName('p')[0].getAttribute('class');
"opener"
//我们可以用更简便的方法查找p标签的属性 查看class使用className(class是js保留字),id依旧使用id
document.documentElement.getElementsByTagName('p')[0].className;
"opener"
//通过 * 匹配所有标签,可见没有匹配空白
document.documentElement.getElementsByTagName('*').length;
8
getElementsByName()
通过设置好的name,访问元素,返回的是一个数组
document.getElementsByName('aaa')[0].innerHTML;
"first paragraph"
getElementsById()
最常用的方法,通过设定好的id,就可以轻松地访问这些元素
document.getElementById('closer');
<p id="closer">
getElementByClassName();通过元素的class属性寻找元素,返回是一个数组
兄弟节点、body元素及首尾子节点
nextSibling与previousSibling,当我们获取一个节点后,可以通过它们访问上一个或下一个节点。
var para = document.getElementById('closer');
undefined
para.nextSibling; //访问下一个节点
#text "
"
para.previousSibling; //访问上一个节点
#text "
"
body可以看成一个节点,直接访问
document.body;
<body>
document.body.nextSibling;
null
document.body.previousSibling;
#text "
"
firstChild/lastChild,相当于childNodes[0]与childNodes[childNodes.length-1]
document.body.lastChild.previousSibling;
<!-- and that's about it' -->
document.body.childNodes[document.body.childNodes.length-1].previousSibling;
<!-- and that's about it' -->
遍历节点:使用的递归
function walkDOM(n){
do{
console.log(n);
if(n.hasChildNodes()){
walkDOM(n.firstChild);
}
}while(n = n.nextSibling); //js会把 n = n.nextSibling的值 编译成boolean,当没有下一个节点返回null,编译成boolean就是false,也就结束循环了
}
事件
事件就是当你执行一些操作时,页面做出的一系列反应,如点的一个按钮会弹出一个alert这就称为一个事件。
添加事件的三种方法
1、内联HTML属性法
<div onclik="alert('您点击了div的区域')">div内容</div>
2、元素属性性
获得元素,给元素添加onclick方法,与上面作用一致
<html>
<head>
<meta charset="UTF-8">
<title>My page</title>
</head>
<body>
<div>div内容</div>
<script>
var d = document.getElementsByTagName('div')[0]; //获得上面的div元素
d.onclick = function(){ //相当于给div添加onclick属性
alert('您点击了div区域');
}
</script>
</body>
</html>
3、DOM的事件监听器
<html>
<head>
<meta charset="UTF-8">
<title>My page</title>
</head>
<body>
<div>div内容</div>
<script>
var d = document.getElementsByTagName('div')[0]; //获得上面的div元素
d.addEventListener('click',function(){
alert("您点击了div区域");
},false); //false是只冒泡,不捕获事件
</script>
</body>
</html>
捕获法与冒泡法
<html>
<head>
<meta charset="UTF-8">
<title>My page</title>
</head>
<body>
<div>div内容</div>
<script>
var d = document.getElementsByTagName('div')[0]; //获得上面的div元素
d.addEventListener('click',function(){
alert("您点击了div区域");
},false);
var a = document.body;
a.addEventListener('click',function(){
alert("您点击了body区域");
},false);
</script>
</body>
</html>
这时我们不但给div添加了事件,也给body添加了事件,可发现当我们触发div的时候,也一定触发了body。
捕获法是从上到下,对应就是 先触发body的事件,再触发div的事件。
冒泡法就是从下到上,对应的就是先 触发 div的事件,再触发boyd的事件。
这是当第三个参数设置为 true 时,先捕获法再冒泡法,而false是执行冒泡法
阻断传播(在特定环境下,我们不应该执行冒泡法)
var d = document.getElementsByTagName('div')[0]; //获得上面的div元素
d.addEventListener('click',function(e){
alert("您点击了div区域");
e.stopPropagation(); //阻断传播
},false);
只需要在事件对应的方法中添加 e.stopPropagation(); 就可以阻断传播了。这时点击div就不会触发body的事件。
防止默认行为(特别的组件,有自己的行为)
如点击 a 标签就是进行跳转页面。这时我们可以通过 e.preventDefault阻止它的默认行为。
下面,当我们点击a标签后,弹出一个confirm框,当选择 no时阻止它的默认行为
<html>
<head>
<meta charset="UTF-8">
<title>My page</title>
</head>
<body>
<a href="http://www.baidu.com">跳转到百度</a>
<script>
var a = document.getElementsByTagName('a')[0]; //获得上面的div元素
a.addEventListener('click',function(e){
if(!confirm('你确定要进行跳转吗')){
e.preventDefault();
}
},false);
</script>
</body>
</html>
XMLHttpRequest对象
AJAX 异步交互,为什么称为异步是因为当把请求消息发送到服务器后,网页继续执行,不等待服务器传递回消息。当服务器传递回消息后进行处理。
发送请求并处理:
<script>
var xhr;
var myCallback = function(){
if( xhr.readyState === 4 && xhr.status === 200)
alert("服务器已经传递回来信息"+xhr.responseText);
}
xhr = new XMLHttpRequest();
xhr.onreadystatechange = myCallback;//当服务器传递加信息后,用myCallback方法处理
xhr.open('GET','content.html',true); //true是是否采用AJAX,false时会阻塞js等待服务器传递回来信息
xhr.send('');
</script>
与这个html同层次,有一个content.html文件。下面看一下返回值
服务器已经传递回来信息I am <strong> formatted </strong> <em>HTML</em> 。其中I am <strong> formatted </strong> <em>HTML</em> 就是content.html的内容
readyState有五种状态
0 未初始化状态
1 载入请求状态
2 载入完成状态
3 请求交互状态
4 请求完成状态