原生JS DOM

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:实现选项卡



    
        finish js
        
    
    
        
111
邓哥...2222
3333

项目4:实现木块运动停止



    
        
        
        Document
    
    
        
    

项目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.实现点击加速,改变左右键移动速度



    
        
        
        Document
    			
    
        
        
    

项目8:扫雷项目基础:刮奖效果




	
	
	Document
	


	
  • //此处省略400行li样式

高级轮播图

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里面的p

开发经验:尽量不用id写东西,用class
读懂代码——布局,处理细节,居中,两栏布局, 反着布局(淘宝)
商业逻辑编程逻辑相互配合
快速实现页面搭建——实现减少加班
jQuery::实现CSS选择模式选择JS:就是识别CSS
query演示

123

然而强大的querySelector()和querySelectorAll()不能用
原因:
1.在ie7和ie7以下的版本中没有
2.实时性:他们选出的不是实时的
实时的是这样:男生全占起来,一会来了一个迟到的,也算进去

var div = document.getElementsByTagName('div');
var demo = document.getElementsByClassName('demo')[0];
var newDiv = document.createElement('div');
document.body.appendChild(newDiv);

querySelector不是实时性,改的是副本


var div = document.querySelectorAll('div');

(2)遍历节点树

parentNode 父节点 (最顶端的parentNode为#document);
childNodes 子节点们(直系的)
firstChild 第一个子节点
lastChild 最后一个子节点
nextSibling 后一个兄弟元素
previousSibling 前一个兄弟元素

节点的类型

元素节点 —— 1
属性节点 —— 2
文本节点 —— 3
注释节点 —— 8
document —— 9
DocumentFragment —— 11

parentNode演示

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 演示

1

节点讲解demo

123sabchiabs

nextSibling演示

123sabchiabs

(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 ()

案例:实现输入数据的节点数返回




	
	
	Document


	
123

寒假作业:

  1. 笔试面试题汇总
  2. 摹写页面:淘宝,新浪微博,58同城
  3. 技术书

(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操作

  1. getElementById方法定义在Document.prototype上,即Element节点上不能使用。

  2. getElementsByName方法定义在HTMLDocument.prototype上,即非html中的document以外不能使用(xml document,Element)

  3. getElementsByTagName方法定义在Document.prototype 和 Element.prototype上

实现选第一个span

通配符选择器

var div = document.getElementsByTagName('*')[0];//选择所有标签
  1. HTMLDocument.prototype定义了一些常用的属性,body,head,分别指代HTML文档中的body head标签。

  2. Document.prototype上定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代html元素

  3. getElementsByClassName、querySelectorAll、querySelector在Document,Element类中均有定义

3.课堂练习

1.遍历元素节点树,要求不能用children属性

题意1.给出父节点,遍历出子节点ChildNodes

题意2.打印树形结构:div子元素节点们,判断子元素节点是否还有子元素节点,有的话一直递归

网络参考答案




    
        
        
        Document
    
    
        

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




    
        
        Document
    

    
        

4.编辑函数,封装children功能,子元素节点。解决以前部分浏览器的兼容性问题

<div>
    <b>b>
    abc
    
    <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
    
        <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

Element节点的一些属性

innerHTML:取,写入

div.innerHTML = '123';//覆盖
div.innerHTML += '456'//追加
div.innerHTML = "123"
123 234

innerText(火狐不兼容) / textContent(老版本IE不好使)

div.innerText//取出里面东西
div.innerText = 123//覆盖

Element节点的一些方法

ele.setAttribute()设置

div.setAttribute('class','demo');

ele.getAttribute();取

div.getAttribute('id');
123

https://m.sm.cn/

实战项目data-log实现统计点击多少次




小操作

<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 = ""

小练习

  1. 封装remove(); 使得child.remove()直接可以销毁自身
  2. 将目标节点内部的节点顺序逆序。
eg:

封装函数insertAfter;功能类似insertBefort();可忽略老版本浏览器,直接在Element.prototype上编程

原型链上编程好处:this可以表示任何要表示的东西;可以实现继承



    
        
        
        Document
    
    
        

将目标节点内部节点顺序逆序

日期对象 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.csdn.net/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>Documenttitle>
        <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

兼容性比较混乱,用时取两个值相加,因为不可能存在两个同时有值

// 
// 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
适用于怪异模式下的浏览器。去掉就变成怪异模式

浏览器两种渲染模式:标准模式;怪异模式(混杂模式,为了兼容之前版本)

封装兼容性方法,返回浏览器视口尺寸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();

兼容性很好
该方法返回一个对象,对象里面有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

求的是相对于父级的位置演示。忽略自身是否是定位元素,而是距离他有定位的父级的距离

对于无定位父级的元素,返回相对文档的坐标。对于有定位父级的元素,返回相对于最近的有定位的父级的坐标。

把position:static;默认值,父级不设置定位演示

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属性的显示值





    

null:解决伪元素问题


改变伪元素:点击div, 绿色方块变黄





    
    
    Document
    



    

改变两个状态

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];
    }
}

小项目:让方块运动

作业
轮播图
仿照优酷电影主页

脚本化样式表
查找,操作样式表
document.styleSheets
该属性存储了一个html文档里面的所有css样式表的集合

Doctype

1.渲染模式

在多年以前(IE6诞生以前),各浏览器都处于各自比较封闭的发展中(基本没有兼容性可谈)。随着WEB的发展,兼容性问题的解决越来越显得迫切,随即,各浏览器厂商发布了按照标准模式(遵循各厂商制定的统一标准)工作的浏览器,比如IE6就是其中之一。但是考虑到以前建设的网站并不支持标准模式,所以各浏览器在加入标准模式的同时也保留了混杂模式(即以前那种未按照统一标准工作的模式,也叫怪异模式)。

三种标准模式的写法

1.2.3.

待穿插知识点

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() 快速阅读的功能

                    Document                        
start
stop

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能用。

		document	

2.async 异步加载,加载完就执行,async只能加载外部脚本,不能把js写在script 标签里。

1.2 执行时也不阻塞页面


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’。

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) {}
兼容性很好,但是一个元素只能绑定一个处理程序

基本等同于写在HTML行间上

2.obj.addEventListener(type, fn, false);
IE9以下不兼容(w3c标准),可以为一个事件绑定多个处理程序

事件监听机制:不是Js引擎干的,而是webstore做的

可以为一个事件绑定多个处理程序

演示:打印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() {});
                                            
  • a
  • a
  • a
  • a

事件处理程序的运行环境

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).事件冒泡:

结构上非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)

                            Document                        

总结:结构上嵌套,而不是视觉上

(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以下版本

			Document		

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标签默认跳转事件

www.baidu.com

也可以这样,相当于return

demo

事件对象

event || window.event 用于IE

事件源对象
event.target 火狐独有的
event.srcElement Ie独有的
这俩chrome都有

兼容性写法

事件委托

点那个出那个内容

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

优化实现:子元素就能冒泡

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);}

利用事件冒泡,和事件源对象进行处理
优点:

  1. 性能 不需要循环所有的元素一个个绑定事件

  2. 灵活 当有新的子元素时不需要重新绑定事件

职业生涯课老师

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的冲突

随机移动方块项目:鼠标放上去,随机向四面八方移动

事件分类

键盘事件

移动端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

                            Document                                    

focus,blur

                            Document                                        

窗体操作类(window上的事件)

scroll(当滚动条一滚动就触发)

br*100

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就能用

为什么不用?

浏览器时间线


浏览器先认出来就行了,具体加载先不管,认出来直接放树上(见图片)
先解析完,立刻开启新线程异步下载
html刚刚解析完JS就能操作了,不用等HTML解析完
window.onload要等解析完下载完才执行,效率太低

小练习:用position:absoluted模拟fixed定位 js兼容版(IE6没有fixed )

position:top + 原来的top===他原来位置

https://blog.csdn.net/longyin0528/article/details/80777809

作业

1.完善轮播图,加按钮
2.提(qie)取密码框的密码——监听:边写边监听打印
3.输入框功能完善
4.贪食蛇游戏----项目公演
5.扫雷游戏----项目公演:注意闭包

6.N阶菜单栏:display:none/block

7.打方块游戏

想慢,写代码快

你可能感兴趣的:(前端地基,css,html,javascript)