DOM
1.DOM操作演示
Document Object Model
插件emmet学习
DOM定义了表示和修改文档所需的对象、这些对象的行为和属性以及这些对象之间的关系。DOM对象即为宿主对象,由浏览器厂商定义,用来操作html和xml功能的一类对象的集合(不能修改CSS样式表,可以改变行间样式,即通过改变html间接修改css)。也有人称DOM是对HTML以及XML的标准编程接口。
demo案例
项目1:实现点击一下发生变化
var div = document.getElementsByTagName('div')[0];
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.onclick = function(){
this.style.backgroundColor = 'green';
this.style.width = "200px";
this.style.height = "50px";
this.style.borderRadius = "50%";
}
项目2:实现点击变色
var div = document.getElementsByTagName('div')[0];
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
var count = 0;
div.onclick = function(){
count++;
if(count % 2 == 1){
this.style.backgroundColor = "green";
}else{
this.style.backgroundColor = 'red';
}
}
一定要多练,编程思想
项目3:实现选项卡
<!DOCTYPE html>
<html>
<head>
<title>finish js</title>
<style>
.content{
display: none;
width: 200px;
height:200px;
border:2px solid red;
}
.active{
background-color: yellow;
}
/*注意权重*/
</style>
</head>
<body>
<div class="wrapper">
<button class="active">111</button>
<button>222</button>
<button>333</button>
<div class="content" style="display: block">111</div>
<div class="content">邓哥...2222</div>
<div class="content">3333</div>
</div>
<script>
var btn = document.getElementsByTagName('button');
var div = document.getElementsByClassName('content');
for(var i = 0; i < btn.length; i++){
(function (n) {
btn[n].onclick = function (){
for(var j = 0; j < btn.length; j++){
btn[j].className = "";
div[j].style.display = "none";
}
this.className = "active";
div[n].style.display = "block";
}
}(i))//立即执行函数,防止I互相污染
}
</script>
</body>
</html>
项目4:实现木块运动停止
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var div = document.createElement('div');
document.body.appendChild(div);
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.style.position = "absolute";
div.style.left = "0";
div.style.top = "0";
var speed = 1;
var timer = setInterval(function(){
speed += speed/7;
div.style.left = parseInt(div.style.left) + speed + "px";
div.style.top = parseInt(div.style.top) + speed + "px";
if(parseInt(div.style.top) > 200 && parseInt(div.style.left) > 200){
clearInterval(timer);
}
},50);
</script>
</body>
</html>
项目5.实现俄罗斯方块基础
var div = document.createElement('div');
document.body.appendChild(div);
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.style.position = "absolute";
div.style.left = "0";
div.style.top = "0";
document.onkeydown = function(e){
switch(e.which) {
case 38:
div.style.top = parseInt(div.style.top) - 5 + "px";
break;
case 40:
div.style.top = parseInt(div.style.top) + 5 + "px";
break;
case 37:
div.style.left = parseInt(div.style.left) - 5 + "px";
break;
case 39:
div.style.left = parseInt(div.style.left) + 5 + "px";
break;
}
}
项目6.实现按住方向键,加速(待做——js运动)
项目7.实现点击加速,改变左右键移动速度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button style="width:100px;height:50px;
background:linear-gradient(to left, #999, #000, #432,#fcc);
position: fixed;right:0;
top:50%;text-align:center;line-height:50px;color:#fff;font-famliy:arial;">加速</button>
<script>
var btn = document.getElementsByTagName('button')[0];
var div = document.createElement('div');
document.body.appendChild(div);
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.style.position = "absolute";
div.style.left = "0";
div.style.top = "0";
var speed = 5;
btn.onclick = function(){
speed++;
}
document.onkeydown = function(e){
switch(e.which) {
case 38:
div.style.top = parseInt(div.style.top) - speed + "px";
break;
case 40:
div.style.top = parseInt(div.style.top) + speed + "px";
break;
case 37:
div.style.left = parseInt(div.style.left) - speed + "px";
break;
case 39:
div.style.left = parseInt(div.style.left) + speed + "px";
break;
}
}
</script>
</body>
</html>
项目8:扫雷项目基础:刮奖效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
li{
box-sizing: border-box;/*盒模型合理展示*/
float: left;
width: 10px;
height: 10px;
/*border: 1px solid black;*/
}
ul{
list-style: none;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<ul>
<li img-date = "0"></li>
<li img-date = "0"></li>
//此处省略400行li样式
</ul>
<script>
var ul = document.getElementsByTagName('ul')[0];
ul.onmouseover = function(e){//鼠标移入触发什么
var event = e||window.event;
var target = event.target || event.srcElement;
target.style.backgroundColor = "rgb(0,255," + target.getAttribute('img-date') +")";
target.setAttribute('img-date', parseInt(target.getAttribute('img-date'))+ 6);
}
</script>
</body>
</html>
高级轮播图
H5 C3高级动画
2.对节点的增删改查
(1)查看节点
document代表整个文档(是一个对象):位于html标签上层的
document的方法:IE不支持说的是IE9及以下
document.getElementById() | 元素id 在Ie8以下的浏览器,不区分id大小写,而且也返回匹配name属性的元素 |
---|---|
getElementsByTagName() | 标签名放在类数组里面 |
getElementByName(); | 只有部分标签name可生效(表单,表单元素,img,iframe) |
getElementsByClassName() | 类名 -> ie8和ie8以下的ie版本中没有,可以多个class一起 |
querySelector() | css选择器 在ie7和ie7以下的版本中没有 |
querySelectorAll() | css选择器 在ie7和ie7以下的版本中没有 |
页面里面所有的div拿出来——>扔到一个类数组里面去
<div></div>
<div></div>
<div></div>
<p></p>
<script>
var div = document.getElementsByTagName('div');
console.log(div.length);//放在类数组里面了
</script>
选择div里面的p
<div>
<p class="demo"></p>
</div>
<script>
var p = document.getElementsByClassName('demo')[0];
console.log(p);
</script>
开发经验:尽量不用id写东西,用class
读懂代码——布局,处理细节,居中,两栏布局, 反着布局(淘宝)
商业逻辑编程逻辑相互配合
快速实现页面搭建——实现减少加班
jQuery::实现CSS选择模式选择JS:就是识别CSS
query演示
<div>
<strong></strong>
</div>
<div>
<span>
<strong class="demo">123</strong>
</span>
</div>
<script>
var strong = document.querySelector('div>span strong.demo');//选一个
var strong1 = document.querySelectorAll('div>span strong.demo');//选一组
</script>
然而强大的querySelector()和querySelectorAll()不能用
原因:
1.在ie7和ie7以下的版本中没有
2.实时性:他们选出的不是实时的
实时的是这样:男生全占起来,一会来了一个迟到的,也算进去
<div></div>
<div class="demo"></div>
<div></div>
var div = document.getElementsByTagName('div');
var demo = document.getElementsByClassName('demo')[0];
var newDiv = document.createElement('div');
document.body.appendChild(newDiv);
querySelector不是实时性,改的是副本
<script>
var div = document.querySelectorAll('div');
var demo = document.getElementsByClassName('demo')[0];
var newDiv = document.createElement('div');
document.body.appendChild(newDiv);
</script>
var div = document.querySelectorAll('div');
(2)遍历节点树
parentNode | 父节点 (最顶端的parentNode为#document); |
---|---|
childNodes | 子节点们(直系的) |
firstChild | 第一个子节点 |
lastChild | 最后一个子节点 |
nextSibling | 后一个兄弟元素 |
previousSibling | 前一个兄弟元素 |
节点的类型
元素节点 —— 1
属性节点 —— 2
文本节点 —— 3
注释节点 —— 8
document —— 9
DocumentFragment —— 11
parentNode演示
<div>
<strong></strong>
<span></span>
<em></em>
</div>
<script>
var strong = document.getElementsByTagName('strong')[0];
</script>
console.log(strong.parentNode);
console.log(strong.parentNode.parentNode);
console.log(strong.parentNode.parentNode.parentNode);
console.log(strong.parentNode.parentNode.parentNode.parentNode);
console.log(strong.parentNode.parentNode.parentNode.parentNode.parentNode);
childNodes 演示
<div>
<strong>
<span>1</span>
</strong>
<span></span>
<em></em>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
// 要是按照直系元素来说,应该长度为3,但是实际为7,遍历节点数(节点不一定都是html)
</script>
节点讲解demo
<div>
123sabchiabs
<!-- this is comment -->
<strong></strong>
<span></span>
</div>
<script>
console.log(div.childNodes);//7个
</script>
nextSibling演示
<div>
123sabchiabs
<!-- this is comment -->
<strong></strong>
<span></span>
</div>
<script>
// 下一个兄弟节点,不是下一个兄弟元素节点
var strong = document.getElementsByTagName('strong')[0];
console.log(strong.nextSibling);
console.log(strong.nextSibling.nextSibling);
console.log(strong.nextSibling.nextSibling.nextSibling);
</script>
(3)遍历元素节点数
去掉乱七八糟节点
parentElement | 返回当前元素的父元素节点 (IE不兼容) |
---|---|
children | 只返回当前元素的元素子节点 |
node.childElementCount=== node.children.length | 当前元素节点的子元素节点个数(IE不兼容) |
firstElementChild | 返回的是第一个元素节点(IE不兼容) |
lastElementChild | 返回的是最后一个元素节点(IE不兼容) |
nextElementSibling / previousElementSibling | 返回后一个/前一个兄弟元素节点(IE不兼容) |
节点的四个属性
nodeName | 元素的标签名,以大写形式表示,只读 |
---|---|
nodeValue重要 | Text节点或Comment节点的文本内容,可读写 |
nodeType | 该节点的类型,只读 |
attributes | Element 节点的属性集合 |
节点的一个方法 Node.hasChildNodes()——有没有子节点(true/false)
获取节点类型 nodeType ()
案例:实现输入数据的节点数返回
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
123
<!-- This is comment -->
<strong></strong>
<span></span>
<em></em>
<i></i>
<b></b>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
function retElementChild(node) {
//no children
var temp = {
length : 0,
push : Array.prototype.push,
splice : Array.prototype.splice//实现看出来像数组
},
child = node.childNodes,
len = child.length;
for(var i = 0; i < len; i++){
if(child[i].nodeType === 1) {
temp.push(child[i]);
}
}
return temp;
}
console.log(retElementChild(div));
</script>
</body>
</html>
寒假作业:
- 笔试面试题汇总
- 摹写页面:淘宝,新浪微博,58同城
- 技术书
(4)DOM树
Document
Document返回一个函数,document代表整个页面
注意:Document是一个构造函数,但是我不能new,只允许系统new
好处:原形:Document写东西,document也适用,继承关系
构造关系:document---->HTMLDocument.prototype---->Document.prototype
所以:Document.prototype.abc可以受益到document上,且就近继承
关系:
HTMLDocument.prototype={
__proto__:Document.prototype
}
最后一列
HTMLBodyElement.prototype.abc = "demo";
var body = document.getElementsByTagName('body')[0];
var head = document.getElementsByTagName('head')[0];
console.log(head.abc);------>undefined
console.log(body.abc);------>demo
(5)DOM操作
-
getElementById方法定义在Document.prototype上,即Element节点上不能使用。
-
getElementsByName方法定义在HTMLDocument.prototype上,即非html中的document以外不能使用(xml document,Element)
-
getElementsByTagName方法定义在Document.prototype 和 Element.prototype上
实现选第一个span
<div>
<span></span>
</div>
<span></span>
<script>
var div = document.getElementsByTagName('div')[0];//整个文档上找element
var span = div.getElementsByTagName('span')[0];//div下面的span
</script>
通配符选择器
var div = document.getElementsByTagName('*')[0];//选择所有标签
-
HTMLDocument.prototype定义了一些常用的属性,body,head,分别指代HTML文档中的body head标签。
-
Document.prototype上定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代html元素
-
getElementsByClassName、querySelectorAll、querySelector在Document,Element类中均有定义
3.课堂练习
1.遍历元素节点树,要求不能用children属性
题意1.给出父节点,遍历出子节点ChildNodes
题意2.打印树形结构:div子元素节点们,判断子元素节点是否还有子元素节点,有的话一直递归
网络参考答案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<div>
<span>
<a href="" title=""></a>
</span>
</div>
<span></span>
</div>
<div>
<div>
<div>
<span></span>
</div>
</div>
</div>
<script>
var div=document.getElementsByTagName("div")
var a=[];
HTMLElement.prototype.allElements=function(){
var dom=this
for(var i=0;i<dom.children.length;i++){
a.push(dom.children[i])
if(dom.children[i].hasChildNodes()){
// console.log(this.children[i].children[i])
dom.children[i].allElements();
}
}
return a;
}
</script>
</body>
</html>
<script>
var list = [];//用来后面储存获取的元素
function getHDeles(ele) {//ele是形参,代表需要求打印哪个dom树
var children = ele.children;//获取ele下的子元素
for (var i = 0; i < children.length; i++) {//遍历children
var child = children[i]//children每一个子代存起来
list.push(child)//每一个子代存入数组当中
getHDeles(child);//子代也要求子代,继续调用这个函数
}
}
getHDeles(document);
console.log(list)//会打印document下的所有dom树:html,head,meta,body.....
</script>
2.封装函数,返回元素e的第n层祖先元素
<body>
<div>
<strong>
<span>
<i></i>
</span>
</strong>
</div>
<script>
function retParent(elem, n){
while(elem && n) {//elem == null时候
elem = elem.parentElement;
n --;
}
return elem;
}
var i = document.getElementsByTagName('i')[0];
</script>
</body>
3.封装函数,返回元素e的第n个兄弟节点,n为正,返回后面的兄弟节点,n为负,返回前面的,n为0,返回自己。
<div>
<span></span>
<p></p>
<strong></strong>
<i></i>
<address></address>
</div>
<script>
function retSibkling(e, n) {
while(e && n){
if(n > 0) {
e = e.nextElementSibling;
n --;
}else{
e = e.previousElementSibling;
n ++;
}
}
return e;
}
var strong = document.getElementsByTagName('strong')[0];
想兼容IE
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<span></span>
<p></p>
<strong></strong>
<!-- this is comment -->
<i></i>
<address></address>
</div>
<script>
function retSibling(e, n) {
while (e && n) {
if (n > 0) {
if (e.nextElementSibling) {
e = e.nextElementSibling;
} else {
for (e = e.nextSibling; e && e.nodeType != 1; e = e.nextSibling);//这里的e兼容的是null
}
n--;
} else {
if (e.previousElementSibling) {
e = e.previousElementSibling;
} else {
for (e = e.previousSibling; e && e.nodeType != 1; e = e.previousSibling);
}
n++;
}
}
return e;
}
var strong = document.getElementsByTagName('strong')[0];
</script>
</body>
</html>
4.编辑函数,封装children功能,子元素节点。解决以前部分浏览器的兼容性问题
<div>
<b></b>
abc
<!-- this is comment -->
<strong>
<span>
<i></i>
</span>
</strong>
</div>
<script>
Element.prototype.myChildren = function () {
var child = this.childNodes;
var len = child.length;
var arr = [];
for(var i = 0; i < len; i++){
if(child[i].nodeType == 1) {
arr.push(child[i]);
}
}
return arr;
}
var div = document.getElementsByTagName('div')[0];
</script>
5.自己封装hasChildren()方法,不可用children属性
<div>
<b></b>
abc
<!-- this is comment -->
<strong>
<span>
<i></i>
</span>
</strong>
</div>
<script>
Element.prototype.myChildren = function () {
var child = this.childNodes;
var len = child.length;
var arr = [];
for(var i = 0; i < len; i++){
if(child[i].nodeType == 1) {
return true;
}
}
return false;
}
var div = document.getElementsByTagName('div')[0];
</script>
增删改查
增
增加创建元素节点
var div = document.createElement('div');
document.body.appendChild(div);
div.innerHTML = 123;
创建文本节点
var text = document.createTextNode('邓宝宝');
创建注释节点
var comment = document.createComment('this is comment');
创建文档碎片节点
document.createDocumentFragment();
删
他杀
parent.removeChild();其实是剪切
div.removeChild(i);
自杀
i.remove()
替换parent.replaceChild(new, origin);剪切
div.replaceChild(new, origin);
插
appendChild类似push
var div = document.getElementsByTagName('div')[0];
var text = document.createTextNode('邓宝宝');
var span = document.createElement('span');
div.appendChild(text);
div.appendChild(span);
var text1 = document.createTextNode('demo');
span.appendChild(text1);
span.appendChild(text);//剪切插入
为了证明是appendChild剪切
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
div.appendChild(span);
insertBefore div.insertBefore(a, b) == div insert a before b
<div>
<!-- <i></i> -->
<!-- <strong></strong> -->
<span></span>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var strong = document.createElement('strong');
var i = document.createElement('i');
div.insertBefore(strong, span);//strong插入到span前面
div.insertBefore(i, strong);
</script>
Element节点的一些属性
innerHTML:取,写入
div.innerHTML = '123';//覆盖
div.innerHTML += '456'//追加
div.innerHTML = "<span style="background-color:red;color:#fff;font-size:20px">123</span>"
<div>
<span>123</span>
<strong>234</strong>
</div>
innerText(火狐不兼容) / textContent(老版本IE不好使)
div.innerText//取出里面东西
div.innerText = 123//覆盖
Element节点的一些方法
ele.setAttribute()设置
div.setAttribute('class','demo');
ele.getAttribute();取
div.getAttribute('id');
<div>
<span>123</span>
</div>
<script>
div = document.getElementsByTagName('div')[0];
div.setAttribute('id', 'only');
</script>
https://m.sm.cn/
实战项目data-log实现统计点击多少次
<div>
<a href="#" data-log="0">hehe</a>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
var a = document.getElementsByTagName('a')[0];
a.onclick = function () {
console.log(this.getAttribute('data-log'));
}
</script>
小操作
<div></div>
<span></span>
<strong></strong>
<script>
var all = document.getElementsByTagName('*');
for (var i = 0; i < all.length; i++) {
all[i].setAttribute('this.name', all[i].nodeName);
}
</script>
课堂练习
请编写一段JavaScript脚本生成下面这段DOM结构。要求:使用标准的DOM方法或属性。
<div class="example">
<p class="slogan">姬成,你最帅!</p>
</div>
提示 dom.className 可以读写class
var div = document.createElement('div');
var p = document.createElement('p');
div.setAttribute('class', 'example');
p.setAttribute('class', 'slogan');
var text = document.createTextNode('最帅');
p.appendChild(text);
div.appendChild(p);
document.body.appendChild(div);
简化
div.innerHTML =""
改变class/id
div.className = ""
div.id = ""
小练习
- 封装remove(); 使得child.remove()直接可以销毁自身
- 将目标节点内部的节点顺序逆序。
eg:<div> <a></a> <em></em></div>
<div><em></em><a></a></div>
封装函数insertAfter;功能类似insertBefort();可忽略老版本浏览器,直接在Element.prototype上编程
原型链上编程好处:this可以表示任何要表示的东西;可以实现继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<i></i>
<b></b>
<span></span>
</div>
<script>
Element.prototype.insertAfter = function (targetNode, afterNode) {
var beforeNode = afterNode.nextElementSibling;
if(beforeNode == null){
this.appendChild(targetNode);
}else{
this.insertBefore(targetNode, beforeNode);
}
}
var div = document.getElementsByTagName('div')[0];
var b = document.getElementsByTagName('b')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
</script>
</body>
</html>
将目标节点内部节点顺序逆序
<div>
<i></i>
<span></span>
<strong></strong>
</div>
<script>
Element.prototype.eNiXu = function (){
var child = this.children;
len = child.length;
for( var i = 2; i <= len; i++){ //这里要把循环圈数写对(只需循环len-1次),不然下文的剪切就会报错
this.appendChild(child[len-i]); //剪切掉并且增加到this最后面
}
return this;
}
var div = document.getElementsByTagName('div')[0];
console.log(div.eNiXu());
</script>
日期对象 Date()
封装函数,打印当前是何年何月何日何时,几分几秒
官方文档https://www.w3school.com.cn/jsref/jsref_obj_date.asp
// 日期对象,是系统提供好的
var date = new Date();
具体知识看看文档
Date();
getTime() 性能优化验证工具
// 时间戳
// 纪元时间:1970-1-1
// 买电脑验证性能
var firstTime = new Date().getTime();
for(var i = 0; i < 100000000; i++) {
}
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
闹铃:倒计时秒杀
var date = new Date();
date.setMinutes(13);
setInterval(function () {
if(new Date().getTime() - date.getTime() > 1000) {
console.log('老邓是宝宝')
}
},1000)
封装函数,打印当前何年何月何日何时几分几秒——一顿get
var retMyDate=function(){
var date=new Date()
var year=date.getFullYear();
var month=date.getMonth()+1;
var day=date.getDate();
var hour=date.getHours()
var Mi=date.getMinutes()
var se=date.getSeconds()
console.log("今天是"+year+"年"+month+"月"+day+"日"+hour+"时"+Mi+"分"+se+"秒")
}
定时器
setInterval(function () {
console.log('a');
document.write('a');
},1000);
识别time只识别一次
var time = 100;
setInterval(function () {
console.log('a');
document.write('a');
},time);
// time = 200;不起作用
计数器
var i = 0;
setInterval(function () {
i++;
console.log(i);
},1000)
准不准:应该都是1000才准
为什么不准
https://blog.youkuaiyun.com/qq_41494464/article/details/99944633
var firstTime = new Date().getTime();
setInterval(function () {
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
firstTime = lastTime;
}, 1000);
必看书:高性能JS ; 你不知道的JS学透了
setInterval();隔多长时间执行
清除定时器
// clearInterval();
// 定时器唯一标识
var timer = setInterval(function(){},1000);
var timer2 = setInterval(function(){},2000);
// 清除唯一标识
var i = 0;
var timer = setInterval(function(){
console.log(i++);
if(i > 10) {
clearInterval(timer);
}
},10);
setTimeout(); 多长时间后执行,只执行一次
电影5min试看时间
clearInterval();
clearTimeout();
全局对象window上的方法,内部函数this指向window
注意也可以这样 :setInterval(“func()”,1000);
写一个计时器,到一分钟停止
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
input{
border: 1px solid rgba(0,0,0,0.8);
text-align: right;
font-size: 20px;
font-weight: bold;
}
</style>
</head>
<body>
minutes : <input type="text" value = "0">
seconds : <input type="text" value = "0">
<script>
var min = document.getElementsByTagName('input')[0];
var sec = document.getElementsByTagName('input')[1];
var seconds = 0,
minutes = 0;
var timer = setInterval(function(){
seconds++;
if(seconds == 60){
seconds = 0;
minutes++;
}
sec.value = seconds;
min.value = minutes;
if(minutes == 3){
clearInterval(timer);
}
},10)
</script>
</body>
</html>
滚动条
查看滚动条的滚动距离
window.pageXOffset/pageYOffset
IE8及IE8以下不兼容
document.body/documentElement.scrollLeft/scrollTop
兼容性比较混乱,用时取两个值相加,因为不可能存在两个同时有值
// <!-- IE8和IE8以下浏览器 -->
// document.body.scrollLeft/Top ie?
// document.documentElement.scrollLeft/Top ie?
// 以上,只要一个好使,另一个一定为0
document.body.scrollLeft + document.documentElement.scrollLeft
封装兼容性方法,g求滚动轮滚动距离getScrollOffset()
function getScrollOffset() {
if(window.pageXOffset) {
return {
x : window.pageXOffset,
y : window.pageYOffset
}
}else{
return {
x : document.body.scrollLeft + document.documentElement.scrollLeft,
y : document.body.scrollTop + document.documentElement.scrollTop
}
}
}
查看视口的尺寸
window.innerWidth/innerHeight
IE8及IE8以下不兼容
document.documentElement.clientWidth/clientHeight
标准模式下,任意浏览器都兼容
document.body.clientWidth/clientHeight
适用于怪异模式下的浏览器。去掉<!DOCTYPE html>
就变成怪异模式
浏览器两种渲染模式:标准模式;怪异模式(混杂模式,为了兼容之前版本)
封装兼容性方法,返回浏览器视口尺寸getViewportOffset()
function getViewportOffset(){
if(window.innerWidth){
return{
w : window.innerWidth,
h : window.innerHeight
}
}else{
if(document.compatMode === "BackCompat"){//向后兼容
return {
w : document.body.clientWidth,
h : document.body.clientHeight
}
}else{
return {
w : document.documentElement.clientWidth,
h : document.documentElement.clientHeight
}
}
}
}
查看元素的几何尺寸
domEle.getBoundingClientRect();
<div style="width: 100px; height: 100px; position: absolute; top:100px;right: 200px; bottom: 200px; left: 100px;background-color: aqua;"></div>
<script type="text/javascript">
var div = document.getElementsByTagName('div')[0];
console.log(div.getBoundingClientRect());
</script>
兼容性很好
该方法返回一个对象,对象里面有left,top,right,bottom等属性。left和top代表该元素左上角的X和Y坐标,right和bottom代表元素右下角的X和Y坐标
height和width属性老版本IE并未实现
返回的结果并不是“实时的”
查看元素的尺寸(可视区)
dom.offsetWidth,dom.offsetHeight返回的是可视区
想求内容区宽高
div.style.height
查看元素的位置
dom.offsetLeft, dom.offsetTop
求的是相对于父级的位置演示。忽略自身是否是定位元素,而是距离他有定位的父级的距离
<div style="width:300px;height:300px;border:2px solid black;position:relative;top:100px;left:100px;">
<div class="demo"
style="width:100px;height:100px;background-color:red;position:absolute;margin-left:100px;margin-top:100px">
</div>
</div>
<script>
var div = document.getElementsByClassName('demo')[0];
</script>
对于无定位父级的元素,返回相对文档的坐标。对于有定位父级的元素,返回相对于最近的有定位的父级的坐标。
把position:static;默认值,父级不设置定位演示
<div style="width:300px;height:300px;border:2px solid black;position:static;margin-left: 100px;margin-top: 100px;">
<div class="demo"
style="width:100px;height:100px;background-color:red;position:absolute;margin-left:100px;margin-top:100px">
</div>
</div>
<script>
var div = document.getElementsByClassName('demo')[0];
</script>
div.offsetLeft
210:=body8+border2
div.offsetTop
202 塌陷了
dom.offsetParent返回最近的有定位的父级,如无,返回body, body.offsetParent 返回null
eg:求元素相对于文档的坐标getElementPositoin。不知有没有定位父级也不知有定位的父级多少层
思路:看是不是有定位的父级,有定位的父级继续看是不是还有父级,父级在相对于文档
脚本化CSS
1.读写元素css属性
dom.style.prop:必须是写在行间的 可读可写
div.style//这个div所有css ;类数组
div.style.width = '200px'
div.style.['width']
可读写行间样式,没有兼容性问题,碰到float这样的关键字属性,前面应加css
没写在行间的看不到
保留字尽量float — > cssFloat
复合属性必须拆解,
div.style.borderWidth
组合单词变成小驼峰式写法
div.style.backgroundColor = 'green'
写入的值必须是字符串格式
2.查询计算样式
window.getComputedStyle(ele,null); IE8 及 IE8以下不兼容
获取的是当前这个元素 所展示出的一切css属性的显示值
<style>
div{
width: 200px!important;
}
</style>
</head>
<body>
<div style="width:100px;float: left;height: 100px;background-color: red;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
console.log(window.getComputedStyle(div,null).width);//200px
console.log(div.style.width)//100px
</script>
null:解决伪元素问题
<style>
div {
width: 10em;
float: left;
height: 100px;
background-color: orangered;
}
div::after {
content: "";
width: 50px;
height: 50px;
background-color: green;
display: inline-block; /*默认inline*/
}
</style>
<div></div>
<script>
var div = document.getElementsByTagName('div')[0];
console.log(window.getComputedStyle(div, 'after').width);
</script>
改变伪元素:点击div, 绿色方块变黄
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
width: 10em;
float: left;
height: 100px;
background-color: orangered;
}
.green::after {
content: "";
width: 50px;
height: 50px;
background-color: green;
display: inline-block;
}
.yellow::after {
content: "";
width: 50px;
height: 50px;
background-color: yellow;
display: inline-block;
}
</style>
</head>
<body>
<div class='green'></div>
<script>
var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
div.className = 'yellow';
}
</script>
</body>
</html>
改变两个状态
var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
div.style.width = '200px';
div.style.height = '200px';
div.style.backgroundColor = 'green';//这些点DOM操作浪费效率
}
更好的写法–一个.style
就会浪费一点效率
div.onclick = function () {
div.className = "active";
}
.active {
width: 200px;
height: 200px;
background-color: palegreen;
}
计算样式只读
返回的计算样式的值都是绝对值,没有相对单位
<style>
div{
width: 10em;
}
</style>
</head>
<body>
<div style="float: left;height: 100px;background-color: red;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
console.log(window.getComputedStyle(div,null).width);//160px
console.log(window.getComputedStyle(div,null).backgroundColor);//rga()
</script>
IE独有的属性
ele.currentStyle
计算样式只读
返回的计算样式的值不是经过转换的绝对值
封装兼容性方法getStyle(obj,prop);
Var div = document.getElementsByTagName('div')[0];
function getStyle(elem, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop];
} else {
return elem.currentStyle[prop];
}
}
小项目:让方块运动
<div style="width: 100px;height: 100px;background-color: red;position: absolute;left:0;top:0;"></div>
<!-- left:默认auto -->
<script>
function getStyle(elem, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop];
} else {
return elem.currentStyle[prop];
}
}
var div = document.getElementsByTagName('div')[0];
var speed = 3;
var timer = setInterval(function () {
speed += speed / 7;
div.style.left = parseInt(getStyle(div, 'left')) + speed + 'px';
if (parseInt(div.style.left) > 500) {
clearInterval(timer);
}
}, 10);
</script>
作业
轮播图
仿照优酷电影主页
脚本化样式表
查找,操作样式表
document.styleSheets
该属性存储了一个html文档里面的所有css样式表的集合
Doctype
1.渲染模式
在多年以前(IE6诞生以前),各浏览器都处于各自比较封闭的发展中(基本没有兼容性可谈)。随着WEB的发展,兼容性问题的解决越来越显得迫切,随即,各浏览器厂商发布了按照标准模式(遵循各厂商制定的统一标准)工作的浏览器,比如IE6就是其中之一。但是考虑到以前建设的网站并不支持标准模式,所以各浏览器在加入标准模式的同时也保留了混杂模式(即以前那种未按照统一标准工作的模式,也叫怪异模式)。
三种标准模式的写法
1.<!DOCTYPE html>2.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">3.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
待穿插知识点
label or 属性 — > js中表示htmlFor
属性映射 HTML属性 映射到Element属性
讲事件的时候,阻止默认事件记得要拿form提交举例,阻止提交,也要拿a举例,组织跳转—>同时引出javascript:void(0);
img图片预加载
byClassName 自己定义的写法还没写呢
Math.random() 和彩票程序 0-36的随机数
让滚动条滚动
window上有三个方法
scroll(),scrollTo(),scrollBy();
三个方法功能类似,用法都是将x,y坐标传入。即实现让滚动轮滚动到当前位置。
window.scroll(x,y)//当前位置window.scrollTo(x,y)//当前位置window.scrollBy(x,y)//累加滚动
区别:scrollBy()会在之前的数据基础之上做累加。
收起展开项目:收起的时候回到原地。用scroll(),scrollTo()。
思路:点击展开的时候记录当前滚动距离,收起就回来
利用scrollBy() 快速阅读的功能
<!doctype html><html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .demo1 { width: 100px; height: 100px; background-color: orange; color: #fff; font-size: 40px; font-weight: bold; text-align: center; line-height: 100px; position: fixed; bottom: 200px; right: 50px; border-radius: 50%; opacity: 0.5; } .demo2 { width: 100px; height: 100px; background-color: orange; color: green; font-size: 40px; font-weight: bold; text-align: center; line-height: 100px; position: fixed; bottom: 100px; right: 50px; border-radius: 50%; opacity: 0.5; } </style> </head> <body> <div class="demo1">start</div> <div class="demo2">stop</div> <script> var start = document.getElementsByTagName('div')[0]; var stop = document.getElementsByTagName('div')[1]; var timer = 0; var key = true; start.onclick = function () { if (key) { timer = setInterval(function () { window.scrollBy(0, 10); }, 100); key = false; } } stop.onclick = function () { clearInterval(timer); key = true; } // 多次点击start不好使——加锁 </script> </body></html>
BOM
定义:Browser Object Model,定义了操作浏览器的接口
BOM对象: Window, History,Navigator,Screen, Location等
由于浏览器厂商的不同,Bom对象的兼容性极低。一般情况下,我只用其中的部分功能
Window
History对象
Navigator对象
http://www.w3school.com.cn/jsref/dom_obj_navigator.asp
Screen对象
Location对象
location.hash
“#”后是对浏览器操作的,对服务器无效,实际发出的请求也不包含”#”后面的部分
“#”被算作历史记录
json
JSON是一种传输数据的格式(以对象为样板,本质上就是对象,但用途有区别,对象就是本地用的,json是用来传输的,属性名加上双引号)
表示形式
'{ "name" : "deng", "age" : 19}'
JSON.parse(); string — > json
"{"name":"abc","age":112}"JSON.parse(str)
JSON.stringify(); json — > string
var obj = { name: "abc", age: 112}var str = JSON.stringify(obj)--->"{"name":"abc","age":112}"
浏览器演示json13min 接口操作后台——网络学习
知识铺垫:本节
HTML 解析:深度优先原则
domTree + cssTree = randerTree
避免 reflow 重排 dom节点删除,添加
dom节点宽高变化,位置变化,display none
offsetWidth offsetLeft
repaint 重绘
异步加载js
js加载的缺点:加载工具方法没必要阻塞文档,过得js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。
有些工具方法需要按需加载,用到再加载,不用不加载。
javascript 异步加载 的 三种方案
1.defer 异步加载,但要等到dom文档全部解析完才会被执行。只有IE能用。
<head> <meta charset="UTF-8"> <title>document</title> <script type="text/javascript" src="tools.js" defer="defer"> //变成了异步JS,不会阻断HTML CSS,并行下载 var a = 123; </script></head>
2.async 异步加载,加载完就执行,async只能加载外部脚本,不能把js写在script 标签里。
1.2 执行时也不阻塞页面
<script type="text/javascript" src="tools.js" aysnc="aysnc"> //里面不能写东西</script>
3.创建script,插入到DOM中,加载完毕后callBack(常用)
<script> var script = document.createElement('script'); script.type = "text/javascript"; script.src = "alert.js"; document.head.appendChild(script); 外部js alert('老邓')</script>
等待下载
<script> var script = document.createElement('script');//创建 script.type = "text/javascript";//设置 script.src = "alert.js";//读到直接异步下载 document.head.appendChild(script); // test();----还没下载完 setTimeout(function () { test(); },1000);</script>
提示下载
safari chrome firefox opera
var script = document.createElement('script');script.type = "text/javascript";script.src = "alert.js";script.onload = function () { test();}//确保下载完执行,下载不完不执行document.head.appendChild(script);
IE
var script = document.createElement('script');script.type = "text/javascript";script.src = "alert.js";// script.readyState = "loading";"completed" "loaded"script.onreadystatechange = function (){//IE if(script.readyState == "completed"||script.readyState == "loaded"){ test(); }}document.head.appendChild(script);
合并
var script = document.createElement('script');script.type = "text/javascript";script.src = "alert.js";if(script.readyState){ script.onreadystatechange = function (){//IE if(script.readyState == "completed"||script.readyState == "loaded"){ test(); } }}else{ script.onload = function () { test(); }} document.head.appendChild(script);
封装函数
外部函数alert.js
var tools = { test : function(){ console.log('a'); }, demo : function () { }}
function loadScript(url, callback) { var script = document.createElement('script'); script.type = "text/javascript"; if(script.readyState){ script.onreadystatechange = function (){//IE if(script.readyState == "completed"||script.readyState == "loaded"){ callback(); } } }else{ script.onload = function () { callback(); } } script.src = url;//放在后面的原因:先执行绑定事件,在加载文件 document.head.appendChild(script);} // loadScript('alert.js',test);还没解析,不知test是谁loadScript('alert.js',function(){ test();});
优化
function loadScript(url, callback) { var script = document.createElement('script'); script.type = "text/javascript"; if(script.readyState){ script.onreadystatechange = function (){//IE if(script.readyState == "completed"||script.readyState == "loaded"){ eval(callback); } } }else{ script.onload = function () { eval(callback); } } script.src = url;//放在后面的原因:先执行绑定事件,在加载文件 document.head.appendChild(script);} // loadScript('alert.js',test);还没解析,不知test是谁loadScript('alert.js',"test()");
最终异步加载写法
function loadScript(url, callback) { var script = document.createElement('script'); script.type = "text/javascript"; if(script.readyState){ script.onreadystatechange = function (){//IE if(script.readyState == "completed"||script.readyState == "loaded"){ tools[callback](); } } }else{ script.onload = function () { tools[callback](); } } script.src = url;//放在后面的原因:先执行绑定事件,在加载文件 document.head.appendChild(script);} // loadScript('alert.js',test);还没解析,不知test是谁loadScript('alert.js',"test");
js加载时间线
优化基础
1、创建Document对象,开始解析web页面。解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段document.readyState = ‘loading’。
<div style="width:100px;height:100px;background-color:red;"></div><script type="text/javascript"> console.log(document.readyState); // window.onload = function(){ // console.log(document.readyState); // } document.onreadystatechange = function (){ console.log(document.readyState); }</script>
<div style="width:100px;height:100px;background-color:red;"></div><script type="text/javascript"> console.log(document.readyState); document.onreadystatechange = function (){ console.log(document.readyState); } document.addEventListener('DOMContentLoaded',function(){ console.log('a'); },false);</script>
2、遇到link外部css,创建线程加载,并继续解析文档。
3、遇到script外部js,并且没有设置async、defer,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档。
4、遇到script外部js,并且设置有async、defer,浏览器创建线程加载,并继续解析文档。
对于async属性的脚本,脚本加载完成后立即执行。(异步禁止使用document.write())
5、遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档。
6、当文档解析完成,document.readyState = ‘interactive’。
7、文档解析完成后,所有设置有defer的脚本会按照顺序执行。(注意与async的不同,但同样禁止使用document.write());
8、document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段。
9、当所有async的脚本加载完成并执行后、img等加载完成后,document.readyState = ‘complete’,window对象触发load事件。
10、从此,以异步响应方式处理用户输入、网络事件等。
事件:
1.事件:交互体验的核心功能
(1).如何绑定事件处理函数
如何绑定事件处理函数,不是绑定事件,事件本身就有
1.ele.onxxx = function (event) {}
兼容性很好,但是一个元素只能绑定一个处理程序
<div style="width: 100px;height: 100px;background-color: red"></div><script> var div = document.getElementsByTagName('div')[0]; div.onclick = function(){ this.style.backgroundColor = 'green'; }//一个对象一个事件 多次赋值会覆盖</script>
基本等同于写在HTML行间上
<div style="width: 100px;height: 100px;background-color: red" οnclick="console.log('a')"></div>
2.obj.addEventListener(type, fn, false);
IE9以下不兼容(w3c标准),可以为一个事件绑定多个处理程序
<div style="width: 100px;height: 100px;background-color: red"></div><script> var div = document.getElementsByTagName('div')[0]; div.addEventListener('click',function(){ console.log('a'); },false);</script>
事件监听机制:不是Js引擎干的,而是webstore做的
可以为一个事件绑定多个处理程序
<div style="width: 100px;height: 100px;background-color: red"></div><script> var div = document.getElementsByTagName('div')[0]; div.addEventListener('click',function(){ console.log('a'); }, false); div.addEventListener('click',function(){ console.log('b'); },false);</script>
演示:打印2个
var div = document.getElementsByTagName('div')[0];div.addEventListener('click',function(){ console.log('a');}, false);div.addEventListener('click',function(){ console.log('a');},false);
演示:打印一个
var div = document.getElementsByTagName('div')[0];div.addEventListener('click', test, false);div.addEventListener('click', test, false);function test(){ console.log('a');}
3.obj.attachEvent(‘on’ + type, fn);
IE独有,一个事件同样可以绑定多个处理程序
var div = document.getElementsByTagName('div')[0];div.attachEvent('onclick',function() {});
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> <style> * { padding: 0; margin: 0; } ul { list-style: none; } li:nth-of-type(2n) { background-color: red; } li:nth-of-type(2n-1) { background-color: green; } </style> </head> <body> <ul> <li>a</li> <li>a</li> <li>a</li> <li>a</li> </ul> <script> var liCollection = document.getElementsByTagName('li'); for (var i = 0; i < liCollection.length; i++) { (function(j) { liCollection[j].onclick = function() { console.log(j); } }(i)); } </script> </body></html>
事件处理程序的运行环境
1.ele.onxxx = function (event) {}
程序this指向是dom元素本身
var div = document.getElementsByTagName('div')[0];div.onclick = function(){ console.log(this);}
2.obj.addEventListener(type, fn, false);
程序this指向是dom元素本身
var div = docuemnt.getElementsByTagName('div')[0];div.addEventListener('click',function(){ console.log(this);},false);
3.obj.attachEvent(‘on’ + type, fn);
程序this指向window
var div = docuemnt.getElementsByTagName('div')[0];div.attchEvent('click', function(){ // console.log(this);---window handle.call(div);//让this指向div});// 想让this指向divfunction handle(){ // this. //事件处理程序}
(2).解除事件处理程序
ele.onclick = false/‘’/null;
var div = document.getElementsByTagName('div')[0];div.onclick = function(){ console.log('a'); this.onclick = null;}
ele.removeEventListener(type, fn, false);
var div = document.getElementsByTagName('div')[0];div.addEventListener('click,test,false');function test(){ console.log('a');}/* div.addEventListener('click,function (){},false'); 这样用不了,永远接触不掉了,匿名函数*/div.removeEventListener('click',test,false);
ele.detachEvent(‘on’ + type, fn);同上
注:若绑定匿名函数,则无法解除
2.事件处理模型
(1).事件冒泡:
结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .wrapper{ width: 300px; height: 300px; background-color: red; } .content{ width: 200px; height: 200px; background-color: green; } .box{ width: 100px; height: 100px; background-color: orange; } </style> </head> <body> <div class="wrapper"> <div class="content"> <div class="box"></div> </div> </div> <script> var wrapper = document.getElementsByClassName('wrapper')[0]; var content = document.getElementsByClassName('content')[0]; var box = document.getElementsByClassName('box')[0]; wrapper.addEventListener('click', function () { console.log('wrapper'); },false); content.addEventListener('click', function () { console.log('content'); },false); box.addEventListener('click', function () { console.log('box'); },false); </script> </body></html>
总结:结构上嵌套,而不是视觉上
(2).事件捕获:
结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自底向上)和冒泡区别:改成true,与冒泡正好相反,先抓父级,后子元素
IE没有捕获事件
一个对象的一个事件类型只能存在一个事件模型,要么时间冒泡,要么事件捕获
说法:点击最外层,最外面捕获事件并且执行,中间捕获并且执行,最里面叫事件执行
同一个对象的同一事件类型上面绑定了两个事件处理函数,一个叫事件冒泡,一个事件捕获这两个执行顺序如何?
触发顺序,先捕获,后冒泡
<script> var wrapper = document.getElementsByClassName('wrapper')[0]; var content = document.getElementsByClassName('content')[0]; var box = document.getElementsByClassName('box')[0]; wrapper.addEventListener('click', function () { console.log('wrapper') },true); content.addEventListener('click', function () { console.log('content') },true); box.addEventListener('click', function () { console.log('box') },true); wrapper.addEventListener('click', function () { console.log('wrapperBubble') },false); content.addEventListener('click', function () { console.log('contentBubble') },false); box.addEventListener('click', function () { console.log('boxBubble') },false);</script>
如果换换顺序:两个捕获结束,到了黄色区域的执行,谁先绑定谁先执行
var wrapper = document.getElementsByClassName('wrapper')[0];var content = document.getElementsByClassName('content')[0];var box = document.getElementsByClassName('box')[0];wrapper.addEventListener('click', function () { console.log('wrapperBubble')},false);content.addEventListener('click', function () { console.log('contentBubble')},false);box.addEventListener('click', function () { console.log('boxBubble')},false);wrapper.addEventListener('click', function () { console.log('wrapper')},true);content.addEventListener('click', function () { console.log('content')},true);box.addEventListener('click', function () { console.log('box')},true);
focus,blur,change,submit,reset,select 等事件不冒泡
(3).取消冒泡和阻止默认事件
取消冒泡:
W3C标准 event.stopPropagation();但不支持ie9以下版本
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .wrapper{ width: 300px; height: 300px; background-color: red; } </style></head><body> <div class="wrapper"> </div> <script> document.onclick = function(){ console.log('你闲的呀'); } var div = document.getElementsByTagName('div')[0]; div.onclick = function(e) { e.stopPropagation();//取消冒泡 this.style.background = "green"; } </script></body></html>
IE,谷歌有 event.cancelBubble = true;
div.onclick = function(e) { e.cancelBubble = true; this.style.background = "green";}
阻止默认事件:
默认事件 — 表单提交,a标签跳转,右键菜单等
document.oncontextmenu = function(){ console.log('a');}
1.return false; 以对象属性的方式注册的事件才生效,只有句柄绑定的事件才好使
document.oncontextmenu = function(){ console.log('a'); return false;}
2.event.preventDefault(); W3C标注,IE9以下不兼容
document.oncontextmenu = function(e){ console.log('a'); e.preventDefault();}
3.event.returnValue = false; 兼容IE
document.oncontextmenu = function(e){ console.log('a'); e.returnValue = false;}
a标签默认跳转事件
<!-- br*100 --><a href="#">www.baidu.com</a><!-- br*100 --><script> var a = document.getElementsByTagName('a')[0]; a.onclick = function() { return false; } function cancelHandler(event) { if(event.preventDefault) { event.preventDefault(); }else{ event.returnValue = false; } }</script>
也可以这样,相当于return
<!-- <a href="javascript:alert('a')">demo</a> --><a href="javascript:void(false)">demo</a>
事件对象
event || window.event 用于IE
<div class="wrapper" style="width: 100px;height: 100px;background-color: red"> <div class="box" style="width: 50px;height: 50px;background-color: green"> </div></div><script> var wrapper = document.getElementsByClassName('wrapper')[0]; var box = document.getElementsByClassName('box')[0]; // 事件源对象 wrapper.onclick = function (e) { var event = e || window.event; }</script>
事件源对象
event.target 火狐独有的
event.srcElement Ie独有的
这俩chrome都有
兼容性写法
<div class="wrapper" style="width: 100px;height: 100px;background-color: red"> <div class="box" style="width: 50px;height: 50px;background-color: green"> </div></div><script> var wrapper = document.getElementsByClassName('wrapper')[0]; var box = document.getElementsByClassName('box')[0]; // 事件源对象 wrapper.onclick = function (e) { var event = e || window.event; var target = event.target || event.srcElement; console.log(target); }</script>
事件委托
点那个出那个内容
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li></ul><body> <script> var li = document.getElementsByTagName('li'); var len = li.length; for(var i = 0; i < len; i++){ li[i].onclick = function() { console.log(this.innerText); } } </script>
优化实现:子元素就能冒泡
var ul = document.getElementsByTagName('ul')[0];ul.onclick = function (e) { var event = e || window.event; var target = event.target || event.srcElement; console.log(target.innerText);}
利用事件冒泡,和事件源对象进行处理
优点:
-
性能 不需要循环所有的元素一个个绑定事件
-
灵活 当有新的子元素时不需要重新绑定事件
职业生涯课老师
5期写的打飞机游戏源码 不卡优化
老面试官会问:什么是事件捕获,三个参数为true,还有没有其他形式的捕获:
真实的事件处理的过程用于解决拖拽鼠标容易出来div这样的麻烦事
// 只在IE好使div.setCapture();//任何地方发生的任何事件都获取到自己身上div.releaseCapture();//释放
事件分类
鼠标事件
click、mousedown、mousemove、mouseup、contextmenu
click = mousedown + mouseup
document.onclick = function(){ console.log('click');}document.onmousedown = function(){ console.log('onmousedown');}document.onmouseup = function(){ console.log('onmouseup'); }
mouseover、mouseout
var div = document.getElementsByTagName('div')[0];div.onmouseover = function (){ div.style.background = "yellow";}div.onmouseout = function (){ div.style.background = "green";}
h5新规范
div.onmouseenter = function () { div.style.background = "yellow";}div.onmouseleave = function () { div.style.background = "green";}
用button来区分鼠标的按键,0/1/2
DOM3标准规定:click事件只能监听左键,只能通过mousedown 和 mouseup来判断鼠标键
document.onmousedown = function(e){ if(e.button == 2){ console.log('right'); }else if(e.button == 0){ console.log('left'); } //中间滚动轮是1}
拖拽影响click,click不影响拖拽,基于这个,实现拖拽不等于点击:时间差
如何解决mousedown和click的冲突
<div style="width:100px;height:100px;background-color:red;"></div><script> var firstTime = 0; var lastTime = 0; var key = false;//开关 document.onmousedown = function () { firstTime = new Date().getTime(); } document.onmouseup = function () { lastTime = new Date().getTime(); if(lastTime - firstTime < 300){ key = true; } } document.onclick = function (){ if(key){ console.log('click'); key = false; } }</script>
随机移动方块项目:鼠标放上去,随机向四面八方移动
事件分类
键盘事件
移动端onmouseon就不好使了,得用touchstart touchmove touchend
keydown keyup keypress
猜想:
keydown+keyup=keypress
但是
document.onkeypress = function () { console.log('keypress');}document.onkeydown = function () { console.log('keydown');}document.onkeyup = function () { console.log('keyup')}
触发顺序: keydown > keypress > keyup
keydown和keypress的区别
keydown 可以响应任意键盘按键(除了fn都有),keypress只可以相应字符类键盘按键(字符时候用它大小写区分开)
keypress返回ASCII码,可以转换成相应字符
演示
document.onkeypress = function (e) { console.log(e);}document.onkeydown = function (e) { console.log(e);}
ASCII转化成字母(验证的时候按空白区域,不是console区域)
document.onkeypress = function (e) { console.log(String.fromCharCode(e.charCode));}
文本操作事件
input change
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> input{ border: 1px solid #01f; } </style> </head> <body> <input type="text"> <script> //改变 var input = document.getElementsByTagName('input')[0]; input.oninput = function (e) { console.log(this.value); } //聚焦+状态改变才触发 input.change = function (e) { console.log(this.value); } </script> </body></html>
focus,blur
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <style> input { border: 1px solid #01f; } </style> </head> <body> <input type="text" value="请输入用户名" style="color:#999" οnfοcus="if(this.value == '请输入用户名') {this.value=''}" οnblur="if(this.value==''){this.value='请输入用户名'}"> </body></html>
窗体操作类(window上的事件)
scroll(当滚动条一滚动就触发)
br*100<script> window.onscroll = function(){ console.log(window.pageXOffset + " " + window.pageYOffset); }</script>
load
<script> window.onload = function(){ var div = document.getElementsByTagName('div')[0]; console.log(div); div.style.width = "100px"; div.style.height = "100px"; div.style.backgroundColor = "red"; }</script><div></div>div在下面,肯定读不到娶不到,用onload就能用
为什么不用?
浏览器时间线
<img src="xx.solarge" alt="">
浏览器先认出来就行了,具体加载先不管,认出来直接放树上(见图片)
先解析完,立刻开启新线程异步下载
html刚刚解析完JS就能操作了,不用等HTML解析完
window.onload要等解析完下载完才执行,效率太低
小练习:用position:absoluted模拟fixed定位 js兼容版(IE6没有fixed )
position:top + 原来的top===他原来位置
https://blog.youkuaiyun.com/longyin0528/article/details/80777809
作业
1.完善轮播图,加按钮
2.提(qie)取密码框的密码——监听:边写边监听打印
3.输入框功能完善
4.贪食蛇游戏----项目公演
5.扫雷游戏----项目公演:注意闭包
6.N阶菜单栏:display:none/block
7.打方块游戏
想慢,写代码快