尚硅谷JavaScript基础教程个人笔记(2)

前言

课程来源:尚硅谷最新版JavaScript基础全套教程完整版(140集实战教学,JS从入门到精通)

一、DOM介绍(Document Object Model)

①DOM即文档对象模型,通过DOM可以来任意来修改网页中各个内容。

②文档:文档指的是网页,一个网页就是一个文档

③对象:对象指将网页中的每一个节点都转换为对象,转换完对象以后,就可以以一种纯面向对象的形式来操作网页了

④模型:模型用来表示节点和节点之间的关系,方便操作页面

⑤节点(Node):节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点,虽然都是节点,但是节点的类型却是不同的。

⑥常用的节点:
文档节点 (Document),代表整个网页

元素节点(Element),代表网页中的标签

属性节点(Attribute),代表标签中的属性

文本节点(Text),代表网页中的文本内容

二.DOM操作

在网页中浏览器已经为我们提供了document对象,它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。例如:document.write()就是通过docemument对象在浏览器中进行写操作。

1.查询操作

document查询方法:
根据元素的id属性查询一个元素节点对象:
document.getElementById(“id属性值”);
例1:

<body>
    <button id="btn">我是一个按钮哦</button>
    <script>
        var btn = document.getElementById("btn");
        console.log(btn);
        btn.innerHTML = "我变了哦";
    </script>
</body>

innerHTML:使用该属性可以获取或设置元素内部的HTML代码。

根据元素的name属性值查询一组元素节点对象:
document.getElementsByName(“name属性值”);

根据标签名来查询一组元素节点对象:
document.getElementsByTagName(“标签名”);

三.事件(EVENT)初步介绍

事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动等等。
我们可以为事件绑定回调函数来响应事件。

可以在标签的事件属性中设置相应的JS代码。

例子:

<button id="btn" onclick="alert('讨厌,你点我干嘛')">我是一个按钮哦</button>

在这里插入图片描述
② 可以通过为对象的指定事件属性设置回调函数的形式来处理事件,像这种事件绑定的函数,称为响应函数。

例子:

<body>
    <button id="btn">我是一个按钮哦</button>
    <script>
        var btn = document.getElementById('btn');
        btn.ondblclick = function() {
            alert("讨厌,点多少下了~");
        }
    </script>
</body>

在这里插入图片描述

四.文档的加载

浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。
如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,
此时将会无法正常获取到DOM对象,导致DOM操作失败。
以下提供两种解决方法:
可以将js代码编写到body的下边

将js代码编写到window.onload = function(){}中,window.onload 对应的响应函数会在整个页面加载完毕以后才执行,所以可以确保代码执行时,DOM对象已经加载完毕了,通过此种方法,我们就可以将JavaScript部分的代码写进< head >标签里。

例子:

<head>
    <meta charset="UTF-8">
    <title></title>
    <script>
        window.onload = function(){
            var btn = document.getElementById('btn');
            btn.ondblclick = function() {
            alert("讨厌,点多少下了~");
        }
        }
    </script>
</head>

在这里插入图片描述

五.DOM查询

A.通过document对象查询
根据元素的id属性查询一个元素节点对象:
document.getElementById(“id属性值”);

根据元素的name属性值查询一组元素节点对象:
document.getElementsByName(“name属性值”);

根据标签名来查询一组元素节点对象:
document.getElementsByTagName(“标签名”);
此方法会给我们返回一个数组对象,所有查询到的元素都会封装到对象中,即使查询到的元素只有一个,也会封装到数组中返回。

如果想要读取元素节点的属性,直接使用:
元素.属性名;
例子:元素.id,元素.name,元素.value,但是读取class属性时不能直接使用class,而是classname。

document.body:获取页面中的body标签。

document.documentElement:获取页面中html根标签。

document.all:获取页面中的所有元素,相当于document.getElementsByTagName("*")。

document.getElementsByClassName():根据元素的class属性值查询一组元素节点对象。(这个方法不支持IE8及以下的浏览器,若想实现此种功能可以使用下面的方法)

document.querySelector(CSS_Select_String):根据CSS选择器去页面中查询一个元素,如果匹配到的元素有多个,则它会返回查询到的第一个元素。
例子:
document.querySelector(".box1 div");

document.querySelectorAll(CSS_Select_String):根据CSS选择器去页面中查询一组元素,会将匹配到所有元素封装到一个数组中返回,即使只匹配到一个。

B.通过具体的元素节点调用
元素.getElementsByTagName():通过标签名查询当前元素的指定后代元素

元素.childNodes:获取当前元素的所有子节点,会获取到空白的文本子节点。childNodes属性会获取包括文本节点在内的所有节点,根据规则标签间的空白也会当成文本节点。

元素.children:获取当前元素的所有子元素。

元素.firstChild:获取当前元素的第一个子节点,会获取到空白的文本子节点。

元素.lastChild:获取当前元素的最后一个子节点。

元素.parentNode:获取当前元素的父元素。

元素.previousSibling:获取当前元素的前一个兄弟节点。
元素.previousElementSibling:获取前一个兄弟元素,IE8及以下不支持。

元素.nextSibling:获取当前元素的后一个兄弟节点

innerHTML和innerText的区别:
这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性,两个属性作用类似,都可以获取到标签内部的内容。
不同是innerHTML会获取到html标签,而innerText会自动去除标签,如果使用这两个属性来设置标签内部的内容时,没有任何区别的。

元素.firstChild.nodeValue:读取标签内部的文本内容。

六.DOM修改

document.createElement(“TagName”):可以用于创建一个元素节点对象,它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回。

document.createTextNode(“textContent”):可以根据文本内容创建一个文本节点对象。

父节点.appendChild(子节点):向父节点中添加指定的子节点。

父节点.insertBefore(新节点,旧节点):将一个新的节点插入到旧节点的前边。

父节点.replaceChild(新节点,旧节点):使用一个新的节点去替换旧节点。

父节点.removeChild(子节点):删除指定的子节点
推荐方式:子节点.parentNode.removeChild(子节点),这样可以实现节点自己删除自己。

元素.innerHTML:以上方法其实均是对元素的innerHTML属性进行修改,因此可以直接对innerHTML进行修改以达到同样的目的。
例子:

<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <script>
        window.onload = function(){
            var li = document.createElement("li");
            li.innerHTML = "singing";
            var hb = document.getElementById("hobby");
            hb.append(li);
        }; 
    </script>
</head>
<body>
    <ul id="hobby">
        <li id="bb">basketball</li>
        <li id="fb">football</li>
        <li id="rn">running</li>
        <li id=dc>dancing</li>
    </ul>
</body>

</html>

这样就不用在创建完li对象之后再创建文本对象,而是直接修改li对象的属性innerHTML以实现绑定的功能。

window.confirm():与alert用法相同,用于弹出一个带有确认和取消按钮的提示框,需要一个字符串作为参数,该字符串将会作为提示文字显现出来。

例子:

confirm("确认要添加吗?");

在这里插入图片描述
如果用户点击确定会返回true,点击取消则返回false。因此常常根据返回的boolean值做是否修改的判断。

⑨易错点:a的索引问题–for循环和响应函数的执行顺序

例子:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <script>
        window.onload = function(){
            var ul = document.getElementById('hobby');
            var a = document.getElementsByTagName("a")[0];
            console.log(a);
            for(var i=0;i<3;i++){
                a.onclick = function(){
                    alert(i);
                };
            }
        };
    </script>
</head>
<body>
    <ul id="hobby">
        <li id="bb">basketball</li>
        <li id="fb">football</li>
        <li id="rn">running</li>
        <li id=dc>dancing</li>
        <li id=a><a href='javascript:;'>TEST</a></li>
    </ul>
</body>

</html>

结果:
在这里插入图片描述
-----》点击超链接
在这里插入图片描述
分析:若只考虑通常的上下文代码关系的话,即若代码从上往下执行,则a的onclick属性应该被连续的赋值了三次,最后一次的结果应该是一个在浏览器返回i = 2的alert语句;但是根据最终的结果发现,最终返回的是3,刚好超出for循环的范围。

解释:for循环会在页面加载完成之后立即执行,而响应函数会在超链接被点击时才执行,当响应函数执行时,for循环早已执行完毕。

七.DOM对CSS的操作

读取内联样式
元素.style.样式名:使用style属性来读取元素的内联样式。例如:
元素.style.width
元素.style.height

注意:
Ⅰ 如果样式名中带有-,则需要将样式名修改为驼峰命名法将-去掉,然后将之后的字母改大写。比如:
backgroundcolor > backgroundColor
borderwidth > borderWidth

Ⅱ 通过style属性设置和读取的都是内联样式,无法读取样式表中的样式。

例子:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        #box {
            width : 200px;
            height : 200px;
            background-color : blue;
        }
    </style>
    <script>
        window.onload = function(){
            box.style.backgroundColor = "yellow";
        }
    </script>
</head>
<body>
    <div id="box"></div>
</body>

</html>

修改内联样式:
语法:元素.style.样式名 = 样式值
通过style修改和读取的样式都是内联样式,由于内联样式的优先级比较高,所以我们通过JS来修改的样式,往往会立即生效。
但是如果样式中设置了!important,则内联样式将不会生效,所以尽量不要为样式添加!important。

读取元素的当前样式
正常浏览器
使用getComputedStyle()
这个方法是window对象的方法,可以返回一个对象,这个对象中保存着当前元素生效样式。如果获取的样式没有设置,则会获取到真实的值,而不是默认值。比如:没有设置width,它不会获取到auto,而是一个确定的长度。
参数:
1.要获取样式的元素
2.可以传递一个伪元素,一般传null
例子:
获取元素的宽度
getComputedStyle(box , null)[“width”];
通过该方法读取到样式都是只读的不能修改

IE8
使用currentStyle
语法:
元素.currentStyle.样式名
例子:
box.currentStyle[“width”]
通过这个属性读取到的样式是只读的不能修改

实现兼容性
先上代码:

/*  
* 定义一个函数,用来获取指定元素的当前的样式  
* 参数:  
* 		obj 要获取样式的元素  
* 		name 要获取的样式名  
*/  
function getStyle(obj , name){  
//对象.属性不存在,不会报错,如果直接寻找对象,(当前作用域到全局作用域)找不到会报错  
    if(window.getComputedStyle){  
        //正常浏览器的方式,具有getComputedStyle()方法  
        return getComputedStyle(obj , null)[name];  
    }else{  
        //IE8的方式,没有getComputedStyle()方法  
        return obj.currentStyle[name];  
    }  	  
}

在if语句中的window是必要的,因为如果没有window,则此时括号内是一个变量,如果解析器找不到这个变量则会报错;但是加了window之后就成了window对象的属性,若找不到这个属性只会返回undefined,而不会报错。

③其他的样式相关的属性
注意:以下样式都是只读的,未指明偏移量都是相对于当前窗口左上角

1.clientHeight:元素的可见高度,包括元素的内容区和内边距的高度。

2.clientWidth:元素的可见宽度,包括元素的内容区和内边距的宽度。

3.offsetHeight:整个元素的高度,包括内容区、内边距、边框。

4.offfsetWidth:整个元素的宽度,包括内容区、内边距、边框。

5.offsetParent:当前元素的定位父元素。即离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位relative,则返回body。

6.offsetLeft,offsetTop:当前元素和定位父元素之间的偏移量。offsetLeft水平偏移量 offsetTop垂直偏移量

7.scrollHeight,scrollWidth:获取元素滚动区域的高度和宽度。

8.scrollTop,scrollLeft:获取元素垂直和水平滚动条滚动的距离

9.判断滚动条是否滚动到底:
Ⅰ垂直滚动:scrollHeight -scrollTop = clientHeight

Ⅱ水平滚动:scrollWidth -scrollLeft = clientWidth

10.滚动条的滚动触发:onscroll,该事件会在元素的滚动条滚动时触发。

11.disabled属性:该属性可以设置一个元素是否禁用,如果设置为true,则元素禁用,如果设置为true,则可用。
例如:

<input type="checkbox" disabled="disabled"/>test

八.事件详细介绍

1.事件对象

当响应函数被调用时,浏览器每次都会将一个事件对象作为实参传递进响应函数中,这个事件对象中封装了当前事件的相关信息,比如:鼠标的坐标,键盘的按键,鼠标的按键,滚轮的方向等。

可以在响应函数中定义一个形参,来使用事件对象,但是在IE8以下浏览器中事件对象是没有实参传递的,而是将事件对象作为window对象的属性保存。

为保证兼容性,可以使用以下代码保证event事件的正确性:

元素.事件 = function(event){  
    event = event || window.event;  
};  
  
元素.事件 = function(e){  
	e = e || event;  
	  
};  

获取鼠标相对于当前可见窗口的坐标:event.clientX和event.clientY
用于获取鼠标在指定窗口内部的坐标。

例子:实现一个功能,在一个指定窗口移动鼠标,在其下方的窗口中显示鼠标的坐标。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>

        #areaDiv {
            border: 1px solid black;
            width: 300px;
            height: 50px;
            margin-bottom: 10px;
        }

        #showMsg {
            border: 1px solid black;
            width: 200px;
            height: 20px;
        }

    </style>
    <script>

        window.onload = function() {
            var areaDiv = document.getElementById('areaDiv');
            var showMsg = document.getElementById('showMsg');
            areaDiv.onmousemove = function(event) {
                event = event || window.event;
                var x = event.clientX;
                var y = event.clientY;
                
                showMsg.innerHTML = 'x='+x+', '+'y='+y;
            }
        };

    </script>
</head>
<body>
    
    <div id='areaDiv'></div>
    <div id='showMsg'></div>

</body>

</html>

P.S.div的偏移量,是相对于整个页面的。

获取鼠标相对于当前页面的坐标:pageX和pageY。

2.事件的冒泡(Bubble)

事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。
事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消
可以将事件对象的cancelBubble设置为true,即可取消冒泡。

例子:

元素.事件 = function(event){  
    event = event || window.event;  
    event.cancelBubble = true;  
};  

3.事件的委派

指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。

事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能

我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的也可以实现此事件功能
我们可以尝试将其绑定给元素的共同的祖先元素,这样当需要实现某些特定元素的事件功能时,可以使用target.className的方式指定特定对象。

target : event中的target表示的触发事件的对象

例子:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>

        

    </style>
    <script>

        window.onload = function() {
            var ul01 = document.getElementById("ul01");
            
            var btn01 = document.getElementById("btn01");
            btn01.onclick = function(){
                var newli = document.createElement("li");
                newli.innerHTML = "<a href='javascript:;' class='clc'>新的链接</a>";
                ul01.appendChild(newli);
            }
            
            ul01.onclick = function(event){
                event = event || window.event;
                if(event.target.className == "clc"){
                    alert("死鬼,点我干嘛~");
                }
            }
        };

    </script>
</head>
<body>
    
    <button id="btn01">增加新连接</button>

    <ul id="ul01">
        <li><a href="javascript:;" class="clc">链接1</a></li>
        <li><a href="javascript:;" class="clc">链接2</a></li>
        <li><a href="javascript:;" class="clc">链接2</a></li>
    </ul>

</body>

</html>

在这里插入图片描述

4.事件的绑定

addEventListener()
通过这个方法也可以为元素绑定响应函数
参数:
1.事件的字符串,不要on
2.回调函数,当事件触发时该函数会被调用
3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false

使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,
这样当事件被触发时,响应函数将会按照函数的绑定顺序执行。

例子:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>

        

    </style>
    <script>

        window.onload = function() {
            var btn01 = document.getElementById("btn01");

            btn01.addEventListener("click", function(){
                alert(1);
            }, false);

            btn01.addEventListener("click", function(){
                alert(2);
            }, false);
        };

    </script>
</head>
<body>
    
    <button id="btn01">点击</button>

</body>

</html>

在这里插入图片描述
但是这个方法不支持IE8及以下的浏览器,若想在IE中实现此功能,考虑使用:

attachEvent()

在IE8中可以使用attachEvent()来绑定事件
参数:
1.事件的字符串,要on
2.回调函数

这个方法也可以同时为一个事件绑定多个处理函数,
不同的是它是后绑定先执行,执行顺序和addEventListener()相反。

例子:

btn01.attachEvent("onclick",function(){  
alert(1);  
});  
  
btn01.attachEvent("onclick",function(){  
alert(2);  
});	 

5.完成bind()函数

由于addEventListener()中的this,是绑定事件的对象,而 attachEvent()中的this,是window ,因此需要统一两个方法this 。所以考虑创建一个函数,用来为指定元素绑定响应函数 ,并解决兼容性问题。

代码:

/*  
			 * 参数:  
			 * 	obj 要绑定事件的对象  
			 * 	eventStr 事件的字符串(不要on)  
			 *  callback 回调函数  
			 */  
function bind(obj , eventStr , callback){  
    if(obj.addEventListener){  
        //大部分浏览器兼容的方式  
        obj.addEventListener(eventStr , callback , false);  
    }else{  
        /*  
					 * this是谁由调用方式决定  
					 * callback.call(obj)  
					 */  
        //IE8及以下  
        obj.attachEvent("on"+eventStr , function(){  
            //在匿名函数中调用回调函数  
            callback.call(obj);  
        });  
    }  
}

6.事件的传播

关于事件的传播网景公司和微软公司有不同的理解
微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,
然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。
网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,
然后在向内传播给后代元素
W3C综合了两个公司的方案,将事件传播分成了三个阶段
1.捕获阶段
在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
2.目标阶段
事件捕获到目标元素,捕获结束开始在目标元素上触发事件
3.冒泡阶段
事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件

如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false。

IE8及以下的浏览器中没有捕获阶段。

九.常用事件

1.鼠标事件

1.1拖拽BOX1元素

拖拽的流程
1.当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
3.当鼠标松开时,被拖拽元素固定在当前位置 onmouseup

例子:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>

        #box1{
            height:100px;
            width:100px;
            position:absolute;
            background-color: red;
        }

    </style>
    <script>

        window.onload = function() {
            var box1 = document.getElementById("box1");
            box1.onmousedown = function(){
                document.onmousemove = function(event){
                    event = event || window.event;
                    var left = event.clientX;
                    var top = event.clientY;
                    box1.style.left = left+"px";
                    box1.style.top = top+"px";
                };

            document.onmouseup = function(){
                document.onmousemove = null;
                document.onmouseup = null;
            }
            };
        };

    </script>
</head>
<body>
    
    <div id="box1"></div>

</body>

</html>

在上例中,div对象会跟着鼠标移动,但是每次移动默认会将左上角与鼠标位置对齐,导致展现出来的效果不太和谐,可以使用简单的加减法解决这一问题:


event.clientX:鼠标相对于当前窗口的水平距离
obj.offsetLeft:元素左侧相对于当前窗口左侧的偏移量
如下图所示:
在这里插入图片描述
其中,绿色即为鼠标clientX的数值,红色为box1的offsetLeft数值,两者相减即可求得当按下鼠标那一刻,box1相对于原位置的水平偏移量ol,即蓝色。最后用鼠标的clientX减去ol,得到box1的left值。
同理,box1的top值也可用clientYoffsetTop经过计算求得。

编写拖拽函数drag()

代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">

        #box1 {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }

        #box2 {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;

            left: 200px;
            top: 200px;
        }
        
    </style>
    <script type="text/javascript">

        window.onload = function () {
            /*  
                         * 拖拽box1元素  
                         *  - 拖拽的流程  
                         * 		1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown  
                         * 		2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove  
                         * 		3.当鼠标松开时,被拖拽元素固定在当前位置	onmouseup  
                         */

            //获取box1  
            var box1 = document.getElementById("box1");
            var box2 = document.getElementById("box2");
            var img1 = document.getElementById("img1");

            //开启box1的拖拽  
            drag(box1);
            //开启box2的  
            drag(box2);

            drag(img1);

        };

        /*  
                     * 提取一个专门用来设置拖拽的函数  
                     * 参数:开启拖拽的元素  
                     */
        function drag(obj) {
            //当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown  
            obj.onmousedown = function (event) {

                //设置box1捕获所有鼠标按下的事件  
                /*  
                             * setCapture()  
                             * 	- 只有IE支持,但是在火狐中调用时不会报错,  
                             * 		而如果使用chrome调用,会报错  
                             */
                /*if(box1.setCapture){  
                                box1.setCapture();  
                            }*/
                obj.setCapture && obj.setCapture();


                event = event || window.event;
                //div的偏移量 鼠标.clentX - 元素.offsetLeft  
                //div的偏移量 鼠标.clentY - 元素.offsetTop  
                var ol = event.clientX - obj.offsetLeft;
                var ot = event.clientY - obj.offsetTop;


                //为document绑定一个onmousemove事件  
                document.onmousemove = function (event) {
                    event = event || window.event;
                    //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove  
                    //获取鼠标的坐标  
                    var left = event.clientX - ol;
                    var top = event.clientY - ot;

                    //修改box1的位置  
                    obj.style.left = left + "px";
                    obj.style.top = top + "px";

                };

                //为document绑定一个鼠标松开事件  
                document.onmouseup = function () {
                    //当鼠标松开时,被拖拽元素固定在当前位置	onmouseup  
                    //取消document的onmousemove事件  
                    document.onmousemove = null;
                    //取消document的onmouseup事件  
                    document.onmouseup = null;
                    //当鼠标松开时,取消对事件的捕获  
                    obj.releaseCapture && obj.releaseCapture();
                };

                /*  
               * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,  
               * 	此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,  
               * 	如果不希望发生这个行为,则可以通过return false来取消默认行为  
               *   
               * 但是这招对IE8不起作用  
               */
                return false;
            };
        }


    </script>
</head>

<body>

    我是一段文字

    <div id="box1"></div>

    <div id="box2"></div>

    <img src="img/an.jpg" id="img1" style="position: absolute;" />
</body>

</html>
1.2 滚轮事件

代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #box1 {
            width: 100px;
            height: 100px;
            background-color: red;
        }
    </style>
    <script type="text/javascript">

        window.onload = function () {


            //获取id为box1的div  
            var box1 = document.getElementById("box1");

            //为box1绑定一个鼠标滚轮滚动的事件  
            /*  
                         * onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,  
                         * 	但是火狐不支持该属性  
                         *   
                         * 在火狐中需要使用 DOMMouseScroll 来绑定滚动事件  
                         * 	注意该事件需要通过addEventListener()函数来绑定  
                         */


            box1.onmousewheel = function (event) {

                event = event || window.event;


                //event.wheelDelta 可以获取鼠标滚轮滚动的方向  
                //向上滚 120   向下滚 -120  
                //wheelDelta这个值我们不看大小,只看正负  

                //alert(event.wheelDelta);  

                //wheelDelta这个属性火狐中不支持  
                //在火狐中使用event.detail来获取滚动的方向  
                //向上滚 -3  向下滚 3  
                //alert(event.detail);  


                /*  
                             * 当鼠标滚轮向下滚动时,box1变长  
                             * 	当滚轮向上滚动时,box1变短  
                             */
                //判断鼠标滚轮滚动的方向  
                if (event.wheelDelta > 0 || event.detail < 0) {
                    //向上滚,box1变短  
                    box1.style.height = box1.clientHeight - 10 + "px";

                } else {
                    //向下滚,box1变长  
                    box1.style.height = box1.clientHeight + 10 + "px";
                }

                /*  
                             * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false  
                             * 需要使用event来取消默认行为event.preventDefault();  
                             * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错  
                             */
                event.preventDefault && event.preventDefault();


                /*  
                             * 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,  
                             * 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为  
                             */
                return false;




            };

            //为火狐绑定滚轮事件  
            bind(box1, "DOMMouseScroll", box1.onmousewheel);


        };


        function bind(obj, eventStr, callback) {
            if (obj.addEventListener) {
                //大部分浏览器兼容的方式  
                obj.addEventListener(eventStr, callback, false);
            } else {
                /*  
                             * this是谁由调用方式决定  
                             * callback.call(obj)  
                             */
                //IE8及以下  
                obj.attachEvent("on" + eventStr, function () {
                    //在匿名函数中调用回调函数  
                    callback.call(obj);
                });
            }
        }

    </script>
</head>

<body style="height: 2000px;">

    <div id="box1"></div>

</body>

</html>

2.键盘事件

2.1 键盘事件

onkeydown:按键被按下
对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发。
当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。

onkeyup
按键被松开,只会触发一次。

P.S.键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document。

2.2 键盘事件附带的属性

keyCode
可以通过keyCode来获取按键的Unicode编码
通过它可以判断哪个按键被按下

除了keyCode,事件对象中还提供了几个属性
altKey
ctrlKey
shiftKey
这三个属性用来判断alt ctrl 和 shift是否被按下
如果按下则返回true,否则返回false

例子1:判断ctrl键和y键是否同时被按下

//console.log(event.keyCode);  
  
//判断一个y是否被按下  
//判断y和ctrl是否同时被按下  
if(event.keyCode === 89 && event.ctrlKey){  
	console.log("ctrl和y都被按下了");  
}  

例子2:实现输入框只能不能输入数字的功能

input.onkeydown = function(event) {  
    event = event || window.event;  
    //数字 48 - 57  
    //使文本框中不能输入数字  
    if(event.keyCode >= 48 && event.keyCode <= 57) {  
        //在文本框中输入内容,属于onkeydown的默认行为  
        //如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中  
        return false;  
    }  
};  
  

在例2中,通过返回false可以关闭input对象的默认操作,使当在输入框中输入数字时,不会显示出来。

2.3 实现方块移动功能

代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">

        #box1 {
            width: 100px;
            height: 100px;
            background-color: red;
            position:absolute;
        }

    </style>
    <script type="text/javascript">

        window.onload = function () {
            box1 = document.getElementById("box1");

            document.onkeydown = function(event){
                event = event || window.event;
                var speed = 10;
                if(event.ctrlKey){
                    speed = 50;
                }

                switch(event.keyCode){
                    case 37:
                        //alert("向左");
                        box1.style.left = box1.offsetLeft - speed + "px";
                        break;
                    case 39:
                        box1.style.left = box1.offsetLeft + speed + "px";
                        break;
                    case 38:
                        box1.style.top = box1.offsetTop - speed + "px";    
                        break;
                    case 40:
                        //alert("向下");
                        box1.style.top = box1.offsetTop + speed + "px";
                        break;
                    default:
                        break;
                }
            }
        }

    </script>
</head>

<body>

    <div id="box1"></div>

</body>

</html>

十.BOM:浏览器对象模型(browser object model)

BOM可以使我们通过JS来操作浏览器
在BOM中为我们提供了一组对象,用来完成对浏览器的操作。

1.BOM对象综述

1.1 Window

代表的是整个浏览器的窗口,同时window也是网页中的全局对象

1.2 Navigator

代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器

1.3 Location

代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面

1.4 History

代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页
而且该操作只在当次访问时有效

1.5 Screen

代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息

这些BOM对象在浏览器中都是作为window对象的属性保存的,
可以通过window对象来使用,也可以直接使用。

2.Navigator

代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了
一般我们只会使用userAgent来判断浏览器的信息,
userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,
不同的浏览器会有不同的userAgent

火狐的userAgent
Mozilla5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko20100101 Firefox50.0

Chrome的userAgent
Mozilla5.0 (Windows NT 6.1; Win64; x64) AppleWebKit537.36 (KHTML, like Gecko) Chrome52.0.2743.82 Safari537.36

IE8
Mozilla4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

IE9
Mozilla5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

IE10
Mozilla5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

IE11
Mozilla5.0 (Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
在IE11中已经将微软和IE相关的标识都已经去除了(为了重新获得广大程序员的芳心,真有你的,微软),所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE了。但可以通过其他的方式来判断:

例子:

alert(navigator.appName);  
  
var ua = navigator.userAgent;  
  
console.log(ua);  
  
if(/firefox/i.test(ua)){  
alert("你是火狐!!!");  
}else if(/chrome/i.test(ua)){  
alert("你是Chrome");  
}else if(/msie/i.test(ua)){  
alert("你是IE浏览器~~~");  
}else if("ActiveXObject" in window){  
alert("你是IE11,枪毙了你~~~");  
}  

3.History

对象可以用来操作浏览器向前或向后翻页
length属性:可以获取到当成访问的链接数量。
back()方法:可以用来回退到上一个页面,作用和浏览器的回退按钮一样。
forward()方法:可以跳转下一个页面,作用和浏览器的前进按钮一样。
go()方法:可以用来跳转到指定的页面,它需要一个整数作为参数。

  • go(1):表示向前跳转一个页面 相当于forward()
  • go(2):表示向前跳转两个页面
  • go(-1):表示向后跳转一个页面
  • go(-2):表示向后跳转两个页面

4.Location

该对象中封装了浏览器的地址栏的信息
如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径),即alert(location);
如果直接将location属性修改为一个完整的路径,或相对路径
则我们页面会自动跳转到该路径,并且会生成相应的历史记录
location = “http:www.baidu.com”;
location = “01.BOM.html”;

4.1 assign()

用来跳转到其他的页面,作用和直接修改location一样。

4.2 reload()

用于重新加载当前页面,作用和刷新按钮一样,
如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面。
location.reload(true);

4.3 replace()

可以使用一个新的页面替换当前页面,调用完毕也会跳转页面
不会生成历史记录,即不能使用回退按钮回退,相当于对当前页面进行了一次重定向的操作,而不是跳转操作。

5.Window

5.1定时器

定时调用

setInterval()
可以将一个函数,每隔一段时间执行一次
参数:
1.回调函数,该函数会每隔一段时间被调用一次
2.每次调用间隔的时间,单位是毫秒

返回值:
返回一个Number类型的数据
这个数字用来作为定时器的唯一标识

clearInterval()
可以用来关闭一个定时器
方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器

clearInterval()可以接收任意参数,
如果参数是一个有效的定时器的标识,则停止对应的定时器
如果参数不是一个有效的标识,则什么也不做

例子:

var num = 1;  
var timer = setInterval(function() {  
	count.innerHTML = num++;  
	if(num == 11) {  
		//关闭定时器  
		clearInterval(timer);  
	}  
}, 1000);  

使用计时器来优化方块移动功能1

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">

        #box1 {
            width: 100px;
            height: 100px;
            background-color: red;
            position:absolute;
        }

    </style>
    <script type="text/javascript">

        window.onload = function () {
            box1 = document.getElementById("box1");
            var speed = 10;
            var dir = 0;

            setInterval(function(){
                switch(dir){
                    case 37:
                        //alert("向左");
                        box1.style.left = box1.offsetLeft - speed + "px";
                        break;
                    case 39:
                        box1.style.left = box1.offsetLeft + speed + "px";
                        break;
                    case 38:
                        box1.style.top = box1.offsetTop - speed + "px";    
                        break;
                    case 40:
                        //alert("向下");
                        box1.style.top = box1.offsetTop + speed + "px";
                        break;
                }
            }, 30)

            document.onkeydown = function(event){
                event = event || window.event;
                if(event.ctrlKey){
                    speed = 50;
                }else{
                    speed = 10;
                }

                dir = event.keyCode;
            };
                document.onkeyup = function(){
                    dir = 0;
                }
        };

    </script>
</head>

<body>

    <div id="box1"></div>

</body>

</html>
延时调用

setTimeout

延时调用一个函数不马上执行,而是隔一段时间以后再执行,而且只会执行一次
延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次
延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择

var timer = setTimeout(function(){
console.log(num++);
},3000);

使用clearTimeout()来关闭一个延时调用
clearTimeout(timer);

⑤使用计时器来优化方块移动功能2(掌握函数化的思维)

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            padding: 0;
            margin: 0;
        }

        #box1 {
            height: 150px;
            width: 150px;
            background-color: red;
            position: absolute;
            left: 0px;
        }

        #box2 {
            height: 150px;
            width: 150px;
            background-color: blue;
            position: absolute;
            left: 0px;
            top: 300px;
        }
    </style>
    <script type="text/javascript">

        window.onload = function () {
            var btn01 = document.getElementById("btn01");
            var btn02 = document.getElementById("btn02");
            var btn03 = document.getElementById("btn03");
            var btn04 = document.getElementById("btn04");
            var box1 = document.getElementById("box1");

            btn01.onclick = function () {
                move(box1, 'left', 800, 10);
            };

            btn02.onclick = function () {
                move(box1, 'left', 0, 10);
            };

            btn03.onclick = function () {
                move(box2, 'left', 800, 10);
            };

            btn04.onclick = function () {
                move(box2, 'width', 800, 20, function () {
                    move(box2, 'height', 800, 20, function () {
                        move(box2, 'top', 300, 20, function () {
                            move(box2, 'width', 150, 20);
                        });
                    });
                });
            };
        };
        /* 
            obj:要执行动画的对象
            attr:想要改变的属性
            target:目的地
            speed:移动的速度
            callback:回调函数,用于执行当前动作完成之后的动作
        */
        function move(obj, attr, target, speed, callback) {
            clearInterval(obj.timer);
            var current = parseInt(getStyle(obj, attr));

            if (current > target) {
                speed = -speed;
            }

            obj.timer = setInterval(function () {
                var oldvalue = parseInt(getStyle(obj, attr));
                var newValue = oldvalue + speed;

                if ((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
                    newValue = target;
                }

                obj.style[attr] = newValue + 'px';

                if (newValue === target) {
                    clearInterval(obj.timer);
                    callback && callback();
                }
            }, 30);
        }

        function getStyle(obj, name) {
            //对象.属性不存在,不会报错,如果直接寻找对象,(当前作用域到全局作用域)找不到会报错  
            if (window.getComputedStyle) {
                //正常浏览器的方式,具有getComputedStyle()方法  
                return getComputedStyle(obj, null)[name];
            } else {
                //IE8的方式,没有getComputedStyle()方法  
                return obj.currentStyle[name];
            }
        }

    </script>
</head>

<body>

    <button id="btn01">box1向右移动</button>
    <button id="btn02">box1向左移动</button>
    <button id="btn03">box2向右移动</button>
    <button id="btn04">对box2进行多重修改</button>
    <br /><br />
    <div id="box1"></div>
    <div id="box2"></div>
    <div style="top:0px; width:0; height:1000px; border-left:1px black solid; position:absolute; left:800px;"></div>

</body>

</html>

5.2类的操作

直接修改元素的类css:

通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面。 这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便 我们希望有一行代码,可以同时修改多个样式。

我们可以通过修改元素的class属性来间接地修改样式。这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器只需要重新渲染页面一次,性能比较好,
并且这种方式,可以使表现和行为进一步的分离。

例子:

//定义一个函数,用来向一个元素中添加指定的class属性值  
/*  
 * 参数:  
 * 	obj 要添加class属性的元素  
 *  cn 要添加的class值  
 * 	  
 */  
function addClass(obj, cn) {  
	if (!hasClass(obj, cn)) {  
		obj.className += " " + cn;  
	}  
}  
/*  
 * 判断一个元素中是否含有指定的class属性值  
 * 	如果有该class,则返回true,没有则返回false  
 * 	  
 */  
function hasClass(obj, cn) {  
	var reg = new RegExp("\\b" + cn + "\\b");  
	return reg.test(obj.className);  
}  
/*  
 * 删除一个元素中的指定的class属性  
 */  
function removeClass(obj, cn) {  
	//创建一个正则表达式  
	var reg = new RegExp("\\b" + cn + "\\b");  
	//删除class  
	obj.className = obj.className.replace(reg, "");  
}  
/*  
 * toggleClass可以用来切换一个类  
 * 	如果元素中具有该类,则删除  
 * 	如果元素中没有该类,则添加  
 */  
function toggleClass(obj , cn){	  
	//判断obj中是否含有cn  
	if(hasClass(obj , cn)){  
		//有,则删除  
		removeClass(obj , cn);  
	}else{  
		//没有,则添加  
		addClass(obj , cn);  
	}  
} 

十一.JSON:JS对象表示法(JavaScript Object Notation)

当我们需要从JS中传递对象到其他语言或从其他语言传递对象到JS中时,由于语法的不同,往往不能直接地传递。这时候可以依靠JSON来解决这一问题。
JS中的对象只有JS自己认识,其他的语言都不认识
JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,
并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号
其他的语法则和JS语法一致

1. JSON中允许的值

1.1 JSON分类:

1.对象 {}
2.数组 []

1.2 JSON中允许的值:

1.字符串
2.数值
3.布尔值
4.null
5.对象
6.数组

例子:

var arr = '[1,2,3,"hello",true]';  
			  
var obj2 = '{"arr":[1,2,3]}';  
  
var arr2 ='[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]';  


2. JSON工具类

JSON转为JS对象
方法:JSON.parse(String)
可以将以JSON字符串转换为js对象
它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回

例子:

    <script type="text/javascript">

        var json = '{"name":"Enoke", "age": 20}';
        var obj = JSON.parse(json);
        console.log(typeof obj);
		console.log(obj);
		
    </script>

在这里插入图片描述
JS对象转为JSON字符串
方法:JSON.stringify(obj)
可以将一个JS对象转换为JSON字符串
需要一个js对象作为参数,会返回一个JSON字符串

例子:

    <script type="text/javascript">

        var json = '{"name":"Enoke", "age": 20}';
        var obj = JSON.parse(json);
        var json_str = JSON.stringify(obj);
        console.log(typeof json_str);
        console.log(json_str);

    </script>

在这里插入图片描述
在IE7中实现JSON功能
JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错。如果希望在这些浏览器中实现预期的功能(仅能实现JSON转为对象的功能),则考虑使用eval()函数。

eval()
这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回
如果使用eval()执行的字符串中含有{},它会将{}当成是代码块
如果不希望将其当成代码块解析,则需要在字符串前后各加一个()

例子:

var str = '{"name":"孙悟空","age":18,"gender":"男"}';  
var obj = eval("("+str+")");  

eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码,
但是在开发中尽量不要使用,首先它的执行性能比较差,然后它还具有安全隐患。

十二.?完?结?撒?花?


版权声明:本文为weixin_44197056原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。