[关闭]
@fantaghiro 2014-09-15T14:42:40.000000Z 字数 31618 阅读 1961

妙味课堂 - JS中级课程

js 学习笔记 妙味课堂 javascript 进行中


DOM基础概念、操作

DOM的概念及节点类型

DOM:Document Object Model 文档对象模型

DOM会把文档看作是一棵树,页面中的每个元素就是树上的一个一个节点;同时DOM定义了很多方法、属性等来操作这棵树中的每一个元素(节点)——每个节点称为DOM节点。

DOM节点

childNodes

元素.childNodes:只读属性 子节点列表集合

childNodes至包含一级子节点,不包含后辈孙级以下的节点

childNodes的兼容性问题:

  1. <ul id="ul1">
  2. <li>1111</li>
  3. <li>1111</li>
  4. <li>1111</li>
  5. <li>1111</li>
  6. </ul>
  1. oUl = document.getElementById('ul1');
  2. alert(oUl.childNodes.length); //在标准浏览器下弹出9;在IE6、7弹出4。因为标准浏览器下,文本元素(在这里是换行符)也包含在childNodes里面了。
  3. for (var i=0; i<oUl.childNodes.length; i++){
  4. oUl.childNodes[i].style.background = 'red'; //在标准浏览器下会报错,因为文本元素(这里是换行符)没有是没有style属性的。
  5. }
  6. //可以通过下面这种方式来解决:
  7. for (var i=0; i<oUl.childNodes.length; i++){
  8. if (oUl.childNodes[i].nodeType == 1) {
  9. oUl.childNodes[i].style.background = 'red';
  10. }
  11. }

children

元素.children:只读 属性 子节点列表集合

这样,如果把childNodes换为children的话,就不用进行nodeType的判断了。

  1. for (var i=0; i<oUl.children.length; i++){
  2. oUl.children[i].style.background = 'red';
  3. }

nodeType

元素.nodeType:只读 属性 当前元素的节点类型

DOM节点的类型nodeType一种有12种,可以查看这里

常用的节点类型包括:元素节点、文本节点、属性节点:

  1. <ul id="ul1" style="color: green">
  2. <li>1111</li>
  3. <li>1111</li>
  4. <li>1111</li>
  5. <li>1111</li>
  6. </ul>
  1. oUl = document.getElementById('ul1');
  2. alert(oUl.nodeType); // 弹出1
  3. alert(oUl.childNodes[0].nodeType); //弹出3
  4. alert(oUl.attributes[0].nodeType); //弹出2
  5. alert(oUl.attributes[0].name); //弹出'id'
  6. alert(oUl.attributes.length); //弹出2
  7. alert(oUl.attributes[0].value); //弹出'ul1'

attributes

元素.attributes:只读 属性 属性列表集合

具体代码可以查看NodeType中js代码中alert的部分。

子节点和兄弟节点的操作

firstChild

元素.firstChild:只读 属性 第一个子节点

firstElementChild

元素.firstElementChild:只读 属性

因此要进行判断:

  1. if (oUl.firstElementChild){
  2. oUl.firstElementChild.style.background = 'red';
  3. } else {
  4. oUl.firstChild.style.background = 'red';
  5. }
  6. //更为简洁的写法:
  7. var oFirst = oUl.firstElementChild || oUl.firstChild;
  8. oFirst.style.background = 'red';

可能存在的问题:

  1. <ul id="ul1">
  2. </ul>
  1. var oUl = document.getElementById('ul1');
  2. var oFirst = oUl.firstElementChild || oUl.firstChild;
  3. if(oFirst){
  4. oFirst.style.background = 'red';
  5. } else {
  6. alert('没有子节点可以设置');
  7. }

以上这段代码会报错。因为在oUl下面没有子元素节点,因此oUl.firstElementChild会返回为null,null不会传给变量oFirst,所以oFirst等于oUl.firstChild,而在标准浏览器下,oUl.firstChild是存在的,是一个文本节点,因此在下面的判断中,oFirst存在,因此走if语句的第一句,但是oFirst是文本节点,没有style可以设置,因此会报错。因此最好的做法是如下:

  1. oUl.children[0].style.background = 'red';

lastChild、lastElementChild

元素.lastChild || 元素.lastElementChild 最后一个子节点

原理与firstChild || firstElementChild相似,不再赘述

nextSibling、previousSibling

元素.nextSibling || 元素.nextElementSibling 下一个兄弟节点

元素.previousSibling || 元素.previousElementSibling 上一个兄弟节点

父节点

parentNode

  1. <ul id="ul1">
  2. <li>1111 <a href="javascript:;">隐藏</a></li>
  3. <li>2222 <a href="javascript:;">隐藏</a></li>
  4. <li>3333 <a href="javascript:;">隐藏</a></li>
  5. <li>4444 <a href="javascript:;">隐藏</a></li>
  6. </ul>
  1. var oA = document.getElementsByTag('a');
  2. for (var i=0; i<oA.length; i++){
  3. oA[i].onclick = function(){
  4. this.parentNode.style.display = 'none';
  5. }
  6. }

元素.parentNode: 只读 属性 只有一个 当前节点的父级节点

offsetParent

  1. <head>
  2. <style>
  3. div {padding: 40px 50px;}
  4. #div1 {background: red;}
  5. #div2 {background: green;}
  6. #div3 {background: orange;}
  7. </style>
  8. </head>
  9. <body id="body1">
  10. <div id="div1">
  11. <div id="div2">
  12. <div id="div3"></div>
  13. </div>
  14. </div>
  15. </body>
  1. var oDiv3 = document.getElementById('div3');
  2. alert(oDiv3.parentNode.id); //弹出div2
  3. alert(oDiv3.offsetParent.id); //弹出body1

上面的代码,如果给div1的style里面加上position: relative; 那么div3的offsetParent就变成了div1

元素.offsetParent:只读 属性 离当前元素最近的一个有定位的父节点

如果给div2的style中添加了zoom: 1,并且其他所有div都没有设置position样式,在IE下,alert(document.getElementById('div2').currentStyle.hasLayout); 会弹出true。这时候div3的offsetParent就会变成div2

元素位置宽高

offsetLeft、offsetTop

元素.offsetLeft\offsetTop:只读 属性 当前元素到定位父级的距离(偏移值)

可以理解为到当前元素的offsetParent的距离

IE7及以下:

如果没有定位父级:

如果有定位父级:

offsetWidth、offsetHeight

高度同理,不再赘述。

getPos()

  1. <head>
  2. <style>
  3. div {padding: 40px 50px;}
  4. #div1 {background: red; position: relative;}
  5. #div2 {background: green; position: relative;}
  6. #div3 {background: orange; position: relative;}
  7. </style>
  8. </head>
  9. <body id="body1">
  10. <div id="div1">
  11. <div id="div2">
  12. <div id="div3"></div>
  13. </div>
  14. </div>
  15. </body>
  1. //通过以下方法可以获得一个元素到达页面的绝对距离,通过各级元素与其offsetParent之间的距离累加的方式得到。
  2. var iTop = 0;
  3. var obj = oDiv3;
  4. while(obj){
  5. iTop += obj.offsetTop;
  6. obj = obj.offsetParent;
  7. }

body的offsetTop是0;body的offsetParent是null。

下面是获取一个元素到达页面的绝对距离的方式,getPos函数。注意,一般工作中,把body的margin值清掉,这样可以避免IE6、7与其他标准浏览器在getPos上的差异。

  1. function getPos(obj){
  2. var pos = {left: 0, top: 0};
  3. while(obj){
  4. pos.left += obj.offsetLeft;
  5. pos.top += obj.offsetTop;
  6. obj = obj.offsetParent;
  7. }
  8. return pos;
  9. }

操作元素属性的多种方式

点的形式和中括号形式

getAttribute、setAttribute、removeAttribute

set/get与用点.的区别:

  1. 用.和[]的形式无法操作元素的自定义属性;getAttribute可以操作元素的自定义属性
  2. 用.和[]的形式来获取src的时候,获取的是一长串绝对路径,但是在IE8以上以及标准浏览器中,用getAttribute('src')可以获取到相对路径(但是在IE7及以下,获取的src还是绝对路径)
  3. 如果给oImg设置了style = "width: 100px;"的属性,那么通过oImg.style.getAttribute('width'); 在IE浏览器下是可以取到值的,但是在标准浏览器下是取不到值的。

元素的创建操作

document.createElement();

document.createElement(标签名);

appendChild()

父级.appendChild(要追加的元素)

insertBefore()

父级.insertBefore(新的元素,指定的被插入的元素);

为了兼容,应做以下判断:

  1. <input type="text" id="text1" /><input type="button" value="留言" id="btn" />
  2. <ul id="ul1"></ul>
  1. var oText = document.getElementById('text1');
  2. var oBtn = document.getElementById('btn');
  3. var oUl = document.getElementById('ul1');
  4. oBtn.onclick = function() {
  5. var oLi = document.createElement('li');
  6. oLi.innerHTML = oText.value;
  7. if ( oUl.children[0] ) {
  8. oUl.insertBefore( oLi, oUl.children[0] );
  9. } else {
  10. oUl.appendChild( oLi );
  11. }
  12. var oA = document.createElement('a');
  13. oA.innerHTML = '删除';
  14. oA.href = 'javascript:;';
  15. oLi.appendChild( oA );
  16. oA.onclick = function() {
  17. oUl.removeChild( this.parentNode );
  18. }
  19. }

removeChild()

父级.removeChild(要删除的节点);

replaceChild()

父级.replaceChild(新节点、被替换节点) 替换子节点

appendChild,insertBefore,replaceChild可以操作静态节点,也可以操作动态生成的节点。

DOM、BOM相关方法及属性

getElementsByClassName

  1. function getElementsByClassName (parent, tagName, className){
  2. var aEls = parent.getElementsByTagName(tagName);
  3. var arr = [];
  4. for(var i=0; i<aEls.length; i++){
  5. /* 以下注释中的这种方法对于拥有多个class的元素不适用
  6. if(aEls[i].className == className){
  7. arr.push(aEls[i]);
  8. }
  9. */
  10. var aClassName = aEls[i].className.split(' ');
  11. for(var j=0; j<aClassName.length; j++){
  12. if(aClassName[j] == className){
  13. arr.push(aEls[i]);
  14. break; //当在某一个元素中找到了对应class马上就进行下一个循环,避免一个元素拥有多个重复class的时候,在数组中添加多次
  15. }
  16. }
  17. }
  18. return arr;
  19. }

addClass、removeClass

  1. function addClass(obj, className){
  2. if(obj.className == ''){
  3. obj.className = className;
  4. } else {
  5. var arrClassName = obj.className.split(' ');
  6. var _index arrIndexOf(arrClassName, className);
  7. if(_index == -1){
  8. obj.className += ' ' + className;
  9. }
  10. }
  11. }
  12. function removeClass(obj, className){
  13. if(obj.className != ''){
  14. var arrClassName = obj.className.split(' ');
  15. var _index arrIndexOf(arrClassName, className);
  16. if(_index != -1){
  17. arrClassName.splice(_index, 1);
  18. obj.className = arrClassName.join(' ');
  19. }
  20. }
  21. }
  22. function arrIndexOf(arr, v){
  23. for(var i=0; i<arr.length; i++){
  24. if(arr[i] == v){
  25. return i;
  26. }
  27. }
  28. return -1;
  29. }

表格操作

  1. <table width="100%" id="tab1" border="1px">
  2. <tr>
  3. <td>1</td>
  4. <td>leo</td>
  5. <td></td>
  6. <td><a href="javascript:;">删除</a></td>
  7. </tr>
  8. <tr>
  9. <td>1</td>
  10. <td>小美</td>
  11. <td></td>
  12. <td><a href="javascript:;">删除</a></td>
  13. </tr>
  14. </table>
  1. var oTab = document.getElementById('tab1');
  2. alert(oTab.children[1].children[1].innerHTML); //什么也弹不出来,提示显示oTab.children[1]未定义,这是因为如果在table中没有添加tbody的话,浏览器会自动隐形添加一个tbody出来。因此,写表格结构时,最好添加上tbody。
  1. <table width="100%" id="tab1" border="1px">
  2. <thead>
  3. <tr>
  4. <th>编号</th>
  5. <th>姓名</th>
  6. <th>性别</th>
  7. <th>操作</th>
  8. </tr>
  9. </thead>
  10. <tbody>
  11. <tr>
  12. <td>1</td>
  13. <td>leo</td>
  14. <td></td>
  15. <td><a href="javascript:;">删除</a></td>
  16. </tr>
  17. <tr>
  18. <td>1</td>
  19. <td>小美</td>
  20. <td></td>
  21. <td><a href="javascript:;">删除</a></td>
  22. </tr>
  23. </tbody>
  24. </table>
  1. var oTab = document.getElementById('tab1');
  2. // alert(oTab.children[0].children[1].children[1].innerHTML); //这是就可以弹出“小美”
  3. alert(oTab.tBodies[0].rows[1].cells[1].innerHTML); //弹出小美,更为直观

表格属性

表格数据的操作

  1. <table width="100%" id="tab1" border="1px">
  2. <thead>
  3. <tr>
  4. <th>编号</th>
  5. <th>姓名</th>
  6. <th>性别</th>
  7. <th>操作</th>
  8. </tr>
  9. </thead>
  10. <tbody></tbody>
  11. </table>
  1. var data = [
  2. {id: 1, username: 'leo', sex: '男'},
  3. {id: 2, username: '小美', sex: '女'},
  4. {id: 3, username: '王亮', sex: '男'},
  5. {id: 4, username: '杜鹏', sex: '男'},
  6. ];
  7. var oTab = document.getElementById('tab1');
  8. var oTbody = oTab.tBodies[0];
  9. for(var i=0; i<data.length; i++){ //表格的创建
  10. var oTr = document.createElement('tr');
  11. if(i%2 == 0){ //各行变色
  12. oTr.style.background = 'white';
  13. } else {
  14. oTr.style.background = 'gray';
  15. }
  16. var oTd = document.createElement('td');
  17. oTd.innerHTML = data[i].id;
  18. oTr.appendChild(oTd);
  19. oTd = document.createElement('td');
  20. oTd.innerHTML = data[i].username;
  21. oTr.appendChild(oTd);
  22. oTd = document.createElement('td');
  23. oTd.innerHTML = data[i].sex;
  24. oTr.appendChild(oTd);
  25. oTd = document.createElement('td');
  26. // oTd.innerHTML = '&nbsp;'; //如果单元格中的内容为空,那么在IE7及以下,这个td不会被创建,为了好看,给最后一列td里面添加一个空格,这样在IE7下,最后一列td也会被创建
  27. oTr.appendChild(oTd);
  28. var oA = document.createElement('a');
  29. oA.innerHTML = '删除';
  30. oA.href = 'javascript:;';
  31. oA.onclick = function(){
  32. oTbody.removeChild(this.parentNode.parentNode);
  33. for(var i=0; i<oTbody.rows.length; i++){
  34. if(i%2 == 0) {
  35. oTbody.rows[i].style.background = 'white';
  36. } else {
  37. oTbody.rows[i].style.background = 'gray';
  38. }
  39. }
  40. }
  41. oTd.appendChild(oA);
  42. oTbody.appendChild(oTr);
  43. }

表单操作

  1. <form id="form1">
  2. <input type="text" name="text1" />
  3. <input type="radio" name="sex" value="男" checked />
  4. <input type="radio" name="sex" value="女" />
  5. <input type="checkbox" name="a" value="html" checked />html
  6. <input type="checkbox" name="a" value="css" />css
  7. <input type="checkbox" name="a" value="javascript" />javascript
  8. <select name="city">
  9. <option value="">请选择城市</option>
  10. <option value="北京">北京</option>
  11. <option value="上海">上海</option>
  12. </select>
  13. <input type="button" value="按钮" name="btn" />
  14. </form>
  1. var oForm = document.getElementById('form1');
  2. oForm.text1.onchange = function(){
  3. alert(this.value); //注意,文本输入框onchange的触发,是在输入完毕之后,鼠标离开该文本框之后触发
  4. }
  5. oForm.sex[0].onchange = function(){
  6. // alert(1);
  7. // alert(this.value);
  8. } //注意:oForm.sex其实是一个元素集合,因为name为sex的单选按钮有两个
  9. oForm.a[0].onchange = function(){
  10. alert(2);
  11. }
  12. // alert(oForm.city.value);
  13. oForm.city.onchange = function(){
  14. alert(this.value);
  15. }
  16. oForm.btn.onclick = function(){
  17. //radio, checkbox 判断当前的选项是否被选中
  18. //alert(oForm.sex[0].checked);
  19. for(var i=0; i<oFrom.sex.length; i++){
  20. if(oForm.sex[i].checked){
  21. alert(oForm.sex[i].value + '被选中了');
  22. } else {
  23. alert(oForm.sex[i].value + '未被选中');
  24. }
  25. }
  26. for(var i=0; i<oFrom.a.length; i++){
  27. if(oForm.a[i].checked){
  28. alert(oForm.a[i].value + '被选中了');
  29. } else {
  30. alert(oForm.a[i].value + '未被选中');
  31. }
  32. }
  33. }

name

onchange事件

表单事件

onsubmit

  1. <form id="form1" action="http://www.baidu.com">
  2. <input type="text" name="text1" />
  3. <input type="text" name="text2" value="111" />
  4. <input type="submit" name="dosubmit" value="提交" />
  5. <input type="reset" name="doreset" value="重置" />
  6. </form>
  1. oForm.onsubmit = function(){
  2. if(this.text1.value == ''){
  3. alert('请输入内容');
  4. return false; //如果没有在文本框中填写任何内容,就写return false,那么点击“提交”按钮,也不会提交到http://www.baidu.com上
  5. }
  6. }
  7. /* 让页面等待一秒钟后自动提交
  8. setTimeout(function(){
  9. oForm.submit();
  10. }, 1000)
  11. */

onreset

注意“重置”的概念:不是清空,而是重置为默认值

  1. oForm.reset = function(){
  2. var re = confirm('你确定要重置吗?');
  3. /*
  4. if(re){
  5. return true;
  6. } else {
  7. return false;
  8. }
  9. */
  10. //上面的代码简写如下:
  11. return re;
  12. //以上所有代码可以简写为:return confirm('您确定要重置吗?');
  13. }

BOM

BOM:Browser Object Model 浏览器对象模型

BOM中大部分是对window对象的操作

open

close

  1. <input type="button" value="打开新窗口" />
  2. <input type="button" value="关闭窗口" />
  3. <input type="button" value="关闭新窗口" />
  1. var aInput = document.getElementsByTagName('input');
  2. var opener = null;
  3. aInput[0].onclick = function(){
  4. // window.open(); 打开新空白页面
  5. // window.open('http://www.baidu.com'); 在新窗口打开百度页面
  6. // window.open('http://www.baidu.com', '_self'); 在本窗口打开百度页面
  7. opener = window.open();
  8. opener.document.body.style.background = 'red';
  9. }
  10. aInput[1].onclick = function(){
  11. window.close(); //不同浏览器处理的方式不同,有兼容性问题
  12. }
  13. aInput[2].onclick = function(){
  14. opener.close();
  15. }

window.navigator.userAgent

window.navigator.userAgent => 浏览器信息

可以通过该属性判断浏览器

  1. if(window.navigator.userAgent.indexOf('MSIE') != -1){ //如果浏览器信息中有MSIE这几个字就代表是IE
  2. alert('我是ie');
  3. } else {
  4. alert('我不是ie');
  5. }

window.location

window:location:浏览器地址栏信息

window.location 看似是一串字符串,其实是一个对象。

文档宽高及窗口事件

可视区尺寸

滚动距离

兼容性问题

可以用如下方式解决兼容性问题:

  1. var scrollTop = document.documentElement.scrollTop || document.body.scrollTop

内容高度

文档高度

兼容性问题

在页面中取文档的高,请先在CSS中将body的margin去掉,然后用document.body.offsetHeight来取文档元素的高,因为这时候文档的高与body的高没有差别。

onscroll

onscroll:当滚动条滚动的时候触发

以一定的时间间隔来计算的。

  1. var i=0;
  2. window.onscroll = function(){
  3. document.title = i++;
  4. }

onresize

onresize:当窗口大小发生改变的时候触发

也是以一定时间间隔来计算的

  1. var i=0;
  2. window.onresize = function(){
  3. document.title = i++;
  4. }

Event事件详解

焦点事件

焦点:使浏览器能够区分用户输入的对象。当一个元素有焦点的时候,那么它就可以接收用户的输入。

我们可以通过一些方式给元素设置焦点

  1. 点击
  2. tab
  3. js

注意:不是所有元素都能够接收焦点。能够响应用户操作的元素才有焦点(例如输入框、链接a、表单元素)。

  1. <input type="text" id="text1" value="请输入内容" />
  2. <input type="button" value="全选" id="btn"/>
  1. var oText = document.getElementById('text1');
  2. var oBtn = document.getElementById('btn');
  3. //onfocus:当元素获取到焦点的时候触发
  4. oText.onfocus = function(){
  5. if(value='请输入内容'){
  6. this.value = '';
  7. }
  8. }
  9. //onblur:当元素失去焦点的时候触发
  10. oText.onblur = function(){
  11. if(this.value == ''){
  12. this.value = '请输入内容';
  13. }
  14. }
  15. oText.focus();
  16. oBtn.onclick = function(){
  17. oText.select();
  18. }

Event对象

event:事件对象。当一个事件发生的时候,和当前这个对象发生的这个事件有关的一些详细的信息都会被临时保存到一个指定的地方,这个地方就是event对象,供我们在需要的时候调用。(比喻:飞机-黑匣子)

  1. function fn1(){
  2. alert(event);
  3. }
  4. fn1(); //不是事件调用的函数,因此这时候event没有内容,显示undefined
  5. document.onclick = fn1; //fn1是事件调用的函数,所以event有内容 这种写法在ff下是弹不出东西的

event对象的兼容性问题

  1. function fn1(ev){
  2. alert(ev);
  3. }
  4. document.onclick = fn1; //在火狐、标准ie下、chrome下都可以弹出事件对象(非标准ie会弹出undefined)

解决兼容性问题的方法:var ev = ev || event;

  1. function fn1(ev) {
  2. var ev = ev || event;
  3. alert(ev);
  4. for(var attr in ev){
  5. console.log(attr + ' = ' + ev[attr]);
  6. }
  7. }
  8. document.onclick = fn1; //在标准浏览器和非标准浏览器下,都能够正确弹出事件对象

clientX \ clientY

  1. function fn1(ev) {
  2. var ev = ev || event;
  3. alert(ev.clientX);
  4. }
  5. document.onclick = fn1; //弹出当前鼠标到可视区左边的距离

示例-跟随鼠标移动的div:

  1. <div id="div1" style="width: 100px; height: 100px; background: red; position: absolute;"></div>
  1. //onmousemove;当鼠标在一个元素上移动的时候触发
  2. //触发频率不是以像素记,而是间隔时间。在一个指定时间内(很短),如果鼠标的位置和上一次的位置发生了变化,那么就会触发一次
  3. var oDiv = document.getElementById('div1');
  4. document.onmousemove = function(){
  5. var ev = ev || event;
  6. var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  7. oDiv.style.left = ev.clientX + 'px';
  8. oDiv.style.top = scrollTop + ev.clientY + 'px';
  9. }

事件流

事件冒泡

事件冒泡:当一个元素接收到事件的时候,会把它接收到的事件传播给它的父级,一直到顶层window,这也被称为js中的事件冒泡机制。

以前是说给某某加一个点击事件,其实这并不准确。应该说是给元素添加事件(处理)函数。例如:oDiv1.onclick = fn1; 这句代码其实是告诉oDiv1,如果它接收到了一个点击事件,那么他就去执行fn1事件函数。这也称之为:事件函数绑定:就是将事件与一个函数绑定。比如将oDiv1.onclick = fn1;这句代码在文件中注释掉,那么点击oDiv1的时候,oDiv1还是能够接收到点击事件,只不过这时候这个点击事件没有与事件函数绑定,因此没有执行什么东西。

//我在马路边捡到一分钱,把他交给警察叔叔(老师就相当于程序员,让我在捡到一分钱的时候,交给警察)(但是如果老师没有告诉你要交给警察叔叔,也不会影响你捡到一分钱。)

我.on马路边捡到一分钱 = function(){
把他交给警察叔叔;
}

阻止冒泡

在当前要阻止冒泡的事件函数中调用:事件对象.cancelBubble = true;

  1. <input type="button" value="按钮" id="btn" />
  2. <div id="div1" style="width: 100px; height: 200px; border: 1px solid red; display: none"></div>
  1. var oBtn = document.getElementById('btn');
  2. var oDiv = document.getElementById('div1');
  3. oBtn.onclick = function(ev){
  4. var ev = ev || event;
  5. ev.cancelBubble = true; //阻止当前对象的当前事件的冒泡
  6. oDiv.style.display = 'block';
  7. }
  8. document.onclick = function(){
  9. /*
  10. setTimeout(function(){
  11. oDiv.style.display = 'none';
  12. }, 1000);
  13. */
  14. oDiv.style.display = 'none';
  15. }

案例:分享到

  1. <div id="div1">
  2. <div id="div2"></div>
  3. </div>
  1. #div1 {width: 100px; height: 200px; background: red; position: absoute; left: -100px; top: 100px;}
  2. #div2 {width: 30px; height: 60px; position: absolute; right: -30px; top: 70px; background: black; color: white; text-align: center;}
  1. var oDiv = document.getElementByid('div1');
  2. oDiv.onmouseover = function(){
  3. this.style.left = '0px';
  4. }
  5. oDiv.onmouseout = function(){
  6. this.style.left = '-100px';
  7. }

注意:上面的案例中,事件都是加给div1的,并没有加给div2。但是,当鼠标从div1移入或移出时,都可以触发设置在div2上的事件函数,因此大大地减少了代码量。

绑定事件的第二种形式

给一个对象绑定一个事件处理函数的第一种形式

对象.事件=事件处理函数(如obj.onclick = fn;)

第一种事件绑定的形式是赋值形式,后赋的值会把先赋的值覆盖掉:
如:

  1. function fn1(){alert(1);}
  2. function fn2(){alert(2);}
  3. document.onclick = fn1;
  4. document.onclick = fn2; //会覆盖前面绑定的fn1

为了给一个对象的同一个事件绑定多个不同的事件函数,所以就产生了给一个元素绑定事件函数的第二种形式.第二种形式是采用函数的形式而不是赋值的形式。

给对象绑定事件处理函数的第二种形式

兼容问题:

是否捕获:默认是false。false:冒泡;true:捕获

call方法

call:函数下的一个方法,call方法的第一个参数可以改变函数执行过程中的内部this的指向;call方法从第二个参数开始就是原来函数的参数列表;如果call方法传入的第一个参数是null,那么就是不改变函数内部的this指向的。

  1. function fn1(){
  2. alert(this);
  3. }
  4. //fn1(); //window
  5. fn1.call(); //调用函数 也就是说:fn1() 可视为等同于 fn1.call() 弹出window
  6. fn1.call(1) //弹出1,因为在fn1里面的this变成了1。
  1. function fn1(a + b){
  2. alert(this);
  3. alert(a + b);
  4. }
  5. fn1.call(1, 20, 30); //先弹出1,然后弹出50
  6. fn1.call(null, 10, 20); //先弹出window对象,然后弹出30

函数绑定封装函数:

  1. function bind(obj, evname, fn){
  2. if(obj.addEventListener){
  3. obj.addEventListener(evname, fn, false);
  4. } else {
  5. obj.attachEvent('on' + evname, function(){
  6. fn.call(obj);
  7. })
  8. }
  9. }
  1. <div id="div1">
  2. <div id="div2">
  3. <div id="div3"></div>
  4. </div>
  5. </div>
  1. var oDiv1 = document.getElementById('div1');
  2. var oDiv2 = document.getElementById('div2');
  3. var oDiv3 = document.getElementById('div3');
  4. function fn1(){
  5. alert(this);
  6. }
  7. //通过将addEventListener的第三个参数设置为true,来设置事件捕获
  8. oDiv1.addEventListener('click', fn1, true); //上面这一句告诉oDiv1:如果有一个进去的事件触发了你,你就去执行fn1这个函数
  9. oDiv2.addEventListener('click', fn1, true);
  10. oDiv3.addEventListener('click', fn1, true);

以上代码,点击oDiv3,弹出顺序是div1 -> div2 ->div3;执行顺序是倒序的。

当点击oDiv3的时候,首先,事件像是一个力一样透过oDiv1、oDiv2到达oDiv3,到达目标对象oDiv3之后,又会像一个反作用力那样,从oDiv3传到oDiv2、oDiv1。也就是说有这个一进一出的过程。如果将addEventListener的第三个参数设置为true,那么进去的那个事件就触发事件函数;相反,如果addEventListener的第三个参数设置为false,那么就是传回来的“反作用力”——传回来的这个事件触发事件函数。

addEventListener的第三个参数true或false监听的就是究竟事件在进去的时候触发,还是返回来冒泡的时候触发。

  1. oDiv1.addEventListener('click', function(){
  2. alert(1);
  3. }, false)
  4. oDiv1.addEventListener('click', function(){
  5. alert(3);
  6. }, true)
  7. oDiv1.addEventListener('click', function(){
  8. alert(2);
  9. }, false)
  10. //弹出顺序是:3 -> 2 -> 1

事件绑定函数的取消

取消普通形式的事件绑定函数:

  1. function fn1(){alert(1);}
  2. function fn2(){alert(2);}
  3. document.onclick = fn1;
  4. document.onclick = null; //通过赋值的形式取消了原来的事件绑定函数fn1

取消第二种形式的事件绑定函数:

键盘事件

onkeydown

onkeydown:当键盘按键按下的时候触发

事件对象.keyCode:数字类型 键盘按键的值 键值 (同样功能的按键,键值一样。例如左侧的ctrl和右侧的ctrl的键值相同)

  1. document.onkeydown = function(ev){
  2. var ev = ev || event;
  3. alert(ev.keyCode);
  4. }
  1. document.onclick = function(ev){
  2. var ev = ev || event;
  3. alert(ev.ctrlKey); //当按下ctrl点击的时候,弹出true;没有按ctrl点击的时候,返回false
  4. }

onkeyup

onkeyup:当键盘按键抬起的时候触发

仿QQ留言本

  1. <input type="text" id="text1" />
  2. <ul id="ul1"></ul>
  1. var oText = document.getElementById('text1');
  2. var oUl = document.getElementById('ul1');
  3. /*
  4. oText.onkeydown = function(){
  5. alert(this.value); //这里会发现,onkeydown的事件触发是在给oText赋值之前,所以这里应该改为onkeyup才行
  6. }
  7. */
  8. oText.onkeyup = function(ev){
  9. var ev = ev || event;
  10. if(this.value != ''){
  11. if(ev.keyCode == 13 && ev.ctrlKey){ //如果同时按住ctrl + 回车
  12. var oLi = document.createElement('li');
  13. oLi.innerHTML = this.value;
  14. if(oUl.children[0]){
  15. oUl.insertBefore(oLi, oUl.children[0]);
  16. } else {
  17. oUl.appendChild(oLi);
  18. }
  19. }
  20. }
  21. }

键盘控制div移动

  1. <div id="div1"></div>
  1. #div1 {width: 100px; height: 100px; background: red; position: absolute;}
  1. var oDiv = document.getElementById('div1');
  2. document.onkeydown = function(ev){
  3. var ev = ev || event;
  4. switch(ev.keyCode){
  5. case 37:
  6. oDiv.style.left = oDiv.offsetLeft - 10 + 'px;'
  7. break;
  8. case 38:
  9. oDiv.style.top = oDiv.offsetTop - 10 + 'px;'
  10. break;
  11. case 39:
  12. oDiv.style.left = oDiv.offsetLeft + 10 + 'px;'
  13. break;
  14. case 40:
  15. oDiv.style.top = oDiv.offsetTop + 10 + 'px;'
  16. break;
  17. }
  18. }

事件默认行为

事件默认行为:当一个事件发生的时候,浏览器自己会默认做的事情

阻止事件默认行为的步骤:

  1. 当前这个行为是什么事件触发的
  2. 在这个事件的处理函数中使用return false;
  1. <body style="height: 2000px"></body>

默认情况下,点击空格,滚动条会向下滚动

  1. document.onkeydown = function(){
  2. return false; //这样就阻止了点击空格,滚动条向下滚动的默认事件
  3. }
  4. document.oncontextmenu = function(){
  5. //alert(1);
  6. return false; //阻止了点击右键,弹出右键菜单的默认行为
  7. }

oncontextmenu:右键菜单事件,当右键菜单(环境菜单、上下文菜单)显示出来的时候触发

自定义右键菜单

  1. <div id="div1"></div>
  1. #div1 {width: 100px; height: 200px; border: 1px solid red; position: absolute; display: none;}
  1. var oDiv = document.ElementById('div1');
  2. document.oncontextmenu = function(ev){
  3. var ev = ev || event;
  4. var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  5. var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
  6. oDiv.style.display = 'block';
  7. oDiv.style.left = scrollLeft + ev.clientX + 'px';
  8. oDiv.style.top = scrollTop + ev.clientY + 'px';
  9. return false;
  10. }
  11. document.onclick = function(){
  12. oDiv.style.display = 'none';
  13. }

事件深入应用

拖拽的原理

简单拖拽:

  1. <div id="div1"></div>
  1. #div1 { width: 100px; height: 100px; background: red; position: absolute; }
  1. var oDiv = document.getElementById('div1');
  2. oDiv.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disX = ev.clientX - this.offsetLeft;
  5. var disY = ev.clientY - this.offsetTop;
  6. document.onmousemove = function(ev){
  7. var ev = ev || event;
  8. oDiv.style.left = ev.clientX - disX + 'px';
  9. oDiv.style.top = ev.clientY - disY + 'px';
  10. }
  11. document.onmouseup = function(){
  12. document.onmousemove = document.onmouseup = null;
  13. }
  14. }

拖拽的问题以及解决办法

  1. 拖拽的时候,如果有文字被选中,会产生问题。
    • 原因:当鼠标按下的时候,如果页面中有文字被选中,会触发浏览器的默认拖拽文字的效果。
    • 解决方法:
      • 标准下:在onmousedown事件的函数里面添加return false;
      • 非标准IE下:通过在ie下设置全局捕获,用setCapture()方法曲线救国
  2. 拖拽图片会有问题,原因和解决方法同上
  1. <input type="button" value="按钮一" />
  2. <input type="button" value="按钮二" />
  1. var aInput = document.getElementsByTagName('input');
  2. aInput[0].setCapture(); //设置全局捕获
  3. aInput[0].onclick = function(){
  4. alert(1);
  5. }
  6. aInput[0].onclick = function(){
  7. alert(2);
  8. }

全局捕获:

  1. var oDiv = document.getElementById('div1');
  2. oDiv.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disX = ev.clientX - this.offsetLeft;
  5. var disY = ev.clientY - this.offsetTop;
  6. if(oDiv.setCapture){ //如果浏览器有setCapture这个方法的话
  7. oDiv.setCapture();//让oDiv将所有后续事件都捕获到自己身上来
  8. }
  9. document.onmousemove = function(ev){
  10. var ev = ev || event;
  11. oDiv.style.left = ev.clientX - disX + 'px';
  12. oDiv.style.top = ev.clientY - disY + 'px';
  13. }
  14. document.onmouseup = function(){
  15. document.onmousemove = document.onmouseup = null;
  16. //释放全局捕获
  17. if(oDiv.releaseCapture){
  18. oDiv.releaseCapture();
  19. }
  20. }
  21. return false; //阻止浏览器的默认行为
  22. }

拖拽的封装和应用扩展-限制范围、磁性吸附

  1. function drag(obj){
  2. obj.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disX = ev.clientX - this.offsetLeft;
  5. var disY = ev.clientY - this.offsetTop;
  6. if(obj.setCapture){
  7. obj.setCapture();
  8. }
  9. document.onmousemove = function(ev){
  10. var ev = ev || event;
  11. obj.style.left = ev.clientX - disX + 'px';
  12. obj.style.top = ev.clientY - disY + 'px';
  13. }
  14. document.onmouseup = function(){
  15. document.onmousemove = document.onmouseup = null;
  16. if(obj.releaseCapture){
  17. obj.releaseCapture();
  18. }
  19. }
  20. return false;
  21. }
  22. }

限制范围的拖拽:

  1. function drag(obj){
  2. obj.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disX = ev.clientX - this.offsetLeft;
  5. var disY = ev.clientY - this.offsetTop;
  6. if(obj.setCapture){
  7. obj.setCapture();
  8. }
  9. document.onmousemove = function(ev){
  10. var ev = ev || event;
  11. var L = ev.clientX - disX;
  12. var T = ev.clientY - disY;
  13. // 限制拖拽范围在页面内
  14. if(L < 0){
  15. L = 0;
  16. } else if( L > document.documentElement.clientWidth - obj.offsetWidth){
  17. L = document.documentElement.clientWidth - obj.offsetWidth;
  18. }
  19. if(T < 0){
  20. T = 0;
  21. } else if(T > document.documentElement.clientHeight - obj.offsetHeight){
  22. T = document.documentElement.clientHeight - obj.offsetHeight;
  23. }
  24. obj.style.left = L + 'px';
  25. obj.style.top = T + 'px';
  26. }
  27. document.onmouseup = function(){
  28. document.onmousemove = document.onmouseup = null;
  29. if(obj.releaseCapture){
  30. obj.releaseCapture();
  31. }
  32. }
  33. return false;
  34. }
  35. }

磁性吸附:

  1. function drag(obj){
  2. obj.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disX = ev.clientX - this.offsetLeft;
  5. var disY = ev.clientY - this.offsetTop;
  6. if(obj.setCapture){
  7. obj.setCapture();
  8. }
  9. document.onmousemove = function(ev){
  10. var ev = ev || event;
  11. var L = ev.clientX - disX;
  12. var T = ev.clientY - disY;
  13. // 限制拖拽范围在页面内
  14. if(L < 100){ //只要把原来的0改为一个范围,例如:100,就实现了磁性吸附的效果
  15. L = 0;
  16. } else if( L > document.documentElement.clientWidth - obj.offsetWidth){
  17. L = document.documentElement.clientWidth - obj.offsetWidth;
  18. }
  19. if(T < 100){
  20. T = 0;
  21. } else if(T > document.documentElement.clientHeight - obj.offsetHeight){
  22. T = document.documentElement.clientHeight - obj.offsetHeight;
  23. }
  24. obj.style.left = L + 'px';
  25. obj.style.top = T + 'px';
  26. }
  27. document.onmouseup = function(){
  28. document.onmousemove = document.onmouseup = null;
  29. if(obj.releaseCapture){
  30. obj.releaseCapture();
  31. }
  32. }
  33. return false;
  34. }
  35. }

碰撞检测

  1. <div id="div1"></div>
  2. <img id="img1" url="1.jpg" />
  1. #div1 { width: 100px; height: 100px; background: red; position: absolute; z-index: 2 }
  2. #img1 { position: absolute; left: 500px; top: 200px; }
  1. function drag(obj){
  2. obj.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disX = ev.clientX - this.offsetLeft;
  5. var disY = ev.clientY - this.offsetTop;
  6. if(obj.setCapture){
  7. obj.setCapture();
  8. }
  9. document.onmousemove = function(ev){
  10. var ev = ev || event;
  11. var L = ev.clientX - disX;
  12. var T = ev.clientY - disY;
  13. //被拖动的元素的四条边
  14. var L1 = L;
  15. var R1 = L + obj.offsetWidth;
  16. var T1 = T;
  17. var B1 = T + obj.offsetHeight;
  18. //被碰撞的元素的四条边(这个例子里面是img元素)
  19. var L2 = oImg.offsetLeft;
  20. var R2 = L2 + oImg.offsetWidth;
  21. var T2 = oImg.offsetTop;
  22. var B2 = T2 + oImg.offsetHeight;
  23. if(R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2){
  24. oImg.src = '1.jpg';
  25. } else {
  26. oImg.src = '2.jpg';
  27. }
  28. obj.style.left = L + 'px';
  29. obj.style.top = T + 'px';
  30. }
  31. document.onmouseup = function(){
  32. document.onmousemove = document.onmouseup = null;
  33. if(obj.releaseCapture){
  34. obj.releaseCapture();
  35. }
  36. }
  37. return false;
  38. }
  39. }

拖拽改变层大小

  1. <div id="div1"></div>
  1. #div1 { width: 100px; height: 100px; background: red; position: absolute; left: 500px; top: 200px; }
  1. var oDiv = document.getElementById('div1');
  2. oDiv.onmousedown = function(ev){
  3. var ev = ev || event;
  4. var disW = this.offsetWidth;
  5. var disX = ev.clientX;
  6. var disL = this.offsetLeft;
  7. var b = '';
  8. if(disX > disL + disW - 10){
  9. b = 'right';
  10. }
  11. if(disX < disL + 10){
  12. b = 'left';
  13. }
  14. document.onmousemove = function(ev){
  15. var ev = ev || event;
  16. switch(b){
  17. case 'left':
  18. oDiv.style.width = disW - (ev.clientX - disX) + 'px';
  19. oDiv.style.left = disL + (ev.clientX - disX) + 'px';
  20. break;
  21. case 'right':
  22. oDiv.style.width = disW + (ev.clientX - disX) + 'px';
  23. break
  24. }
  25. }
  26. document.onmouseup = function(){
  27. document.onmousemove = document.onmouseup = null;
  28. }
  29. return false;
  30. }

滚动条的模拟和扩展运用

  1. <div id="div1">
  2. <div id="div2></div>
  3. </div>
  4. <div id="div3></div>
  1. #div1 { width: 30px; height: 500px; background: black; position: absolute; left: 10px; top: 10px; }
  2. #div2 { width: 30px; height: 30px; background: red; position: absolute; left: 0; top: 0 }
  3. #div3 { width: 500px; height: 500px; background: green; position: absolute; left: 50px; top: 10; }
  1. var oDiv1 = document.getElementById('div1');
  2. var oDiv2 = document.getElementById('div2');
  3. var oDiv3 = document.getElementById('div3');
  4. var iMaxTop = oDiv1.offsetHeight - oDiv2.offsetHeight;
  5. oDiv2.onmousedown = function(ev){
  6. var ev = ev || event;
  7. var disY = ev.clientY - this.offsetTop;
  8. document.onmousemove = function(ev){
  9. var ev = ev || event;
  10. var T = ev.clientY - disY;
  11. if(T < 0){
  12. T = 0;
  13. } else if(T > iMaxTop){
  14. T = iMaxTop;
  15. }
  16. oDiv2.style.top = T + 'px';
  17. var iScale = T / iMaxTop;
  18. oDiv3.style.height = 500 * iScale + 'px';
  19. }
  20. document.onmouseup = function(){
  21. document.onmousemove = document.onmouseup = null;
  22. }
  23. return false;
  24. }

控制内容的滚动

  1. <div id="div1">
  2. <div id="div2"></div>
  3. </div>
  4. <div id="div3>
  5. <div id="div4">这里是一段内容。</div>
  6. </div>
  1. #div1 { width: 30px; height: 500px; background: black; position: absolute; left: 10px; top: 10px; }
  2. #div2 { width: 30px; height: 30px; background: red; position: absolute; left: 0; top: 0 }
  3. #div3 { width: 498px; height: 498px; border: 1px solid green; position: absolute; left: 50px; top: 10; }
  4. #div4 { position: absolute; top: 0; left: 0; }
  1. var oDiv1 = document.getElementById('div1');
  2. var oDiv2 = document.getElementById('div2');
  3. var oDiv3 = document.getElementById('div3');
  4. var oDiv4 = document.getElementById('div4');
  5. var iMaxTop = oDiv1.offsetHeight - oDiv2.offsetHeight;
  6. oDiv2.onmousedown = function(ev){
  7. var ev = ev || event;
  8. var disY = ev.clientY - this.offsetTop;
  9. document.onmousemove = function(ev){
  10. var ev = ev || event;
  11. var T = ev.clientY - disY;
  12. if(T < 0){
  13. T = 0;
  14. } else if(T > iMaxTop){
  15. T = iMaxTop;
  16. }
  17. oDiv2.style.top = T + 'px';
  18. var iScale = T / iMaxTop;
  19. oDiv4.style.top = (oDiv3.clientHeight - oDiv4.offsetHeight) * iScale + 'px';
  20. }
  21. document.onmouseup = function(){
  22. document.onmousemove = document.onmouseup = null;
  23. }
  24. return false;
  25. }

鼠标滚轮和COOKIE

鼠标滚轮事件

也就是说阻止默认行为不是看事件,而是看事件的绑定形式

  1. <div id="div1"></div>
  1. body { height: 2000px; }
  2. #div1 { width: 100px; height: 100px; background: red; }
  1. var oDiv = document.getElementById('div1');
  2. oDiv.onmousewheel = fn;
  3. if(oDiv.addEventListener){
  4. oDiv.addEventListener('DOMMouseScroll', fn, false);
  5. }
  6. function fn(ev){
  7. var ev = ev || event;
  8. var b = true;
  9. if(ev.wheelDelta){
  10. b = ev.wheelDelta > 0 ? true : false;
  11. } else {
  12. b = ev.wheelDelta > 0 ? false : true;
  13. }
  14. if(b){
  15. this.style.height = this.offsetHeight - 10 + 'px';
  16. } else {
  17. this.style.height = this.offsetHeight + 10 + 'px';
  18. }
  19. if(ev.preventDefault){
  20. ev.preventDefault();
  21. }
  22. return false;
  23. }

我们通过document.cookie来获取当前网站下的cookie的时候,得到的是字符串形式的值,它包含了当前网站下所有的cookie。它会把所有的cookie通过一个分号+空格的形式串联起来。

如果我们想长时间存放一个cookie,需要在设置这个cookie的时候,同时给它设置一个过期的时间(这个时间必须是字符串格式)。cookie默认是临时存储的,当浏览器关闭进程的时候,自动销毁。

有关cookie的操作

  1. //document.cookie = '名字=值;expires=' + 字符串格式的时间;
  2. var oDate = new Date();
  3. oDate.setDate( oDate.getDate() + 5 ); //5天以后
  4. //oDate.toGMTString(); //将日期对象转换为字符串格式
  5. //内容最好编码存放,encodeURI
  6. //alert(encodeURI('你好'));
  7. //alert(decodeURI('%E4%BD%A0%E5%A5%BD'));
  8. document.cookie = 'username =' + encodeURI('leo\n你好') + ' leo;expires=' + oDate.toGMTString();
  9. document.cookie = 'age = 32';
  10. alert(decodeURI(document.cookie));
  11. function getCookie(key){
  12. var arr1 = document.cookie.split('; ');
  13. for(var i=; i<arr1.length; i++){
  14. var arr2 = arr1[i].split('=');
  15. if(arr2[0] == key){
  16. return decodeURI(arr2[1]);
  17. }
  18. }
  19. }
  20. alert(getCookie('age'));
  21. function setCookie(key, value, t){
  22. var oDate = new Date();
  23. oDate.setDate( oDate.getDate() + t );
  24. document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString();
  25. }
  26. setCookie('sex', '男', 10);
  27. function removeCookie(key){
  28. setCookie(key, '', -1);
  29. }
  30. removeCookie('username');

cookie的应用-记录登录名

  1. <input type="text" id="username" />
  2. <input type="button" value="登陆" id="login" />
  3. <input type="button" value="删除" id="del" />
  1. var oUsername = document.getElementById('username');
  2. var oLogin = document.getElementById('login');
  3. var oDel = document.getElementById('del');
  4. if(getCookie('username')){
  5. oUsername.value = getCookie('username');
  6. }
  7. oLogin.onclick = function(){
  8. alert('登陆网站成功');
  9. setCookie('username', oUsername.value, 5);
  10. }
  11. oDel.onclick = function(){
  12. removeCookie('username');
  13. oUsername.value = '';
  14. }
  15. function getCookie(key){
  16. var arr1 = document.cookie.split('; ');
  17. for(var i=; i<arr1.length; i++){
  18. var arr2 = arr1[i].split('=');
  19. if(arr2[0] == key){
  20. return decodeURI(arr2[1]);
  21. }
  22. }
  23. }
  24. function setCookie(key, value, t){
  25. var oDate = new Date();
  26. oDate.setDate( oDate.getDate() + t );
  27. document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString();
  28. }
  29. function removeCookie(key){
  30. setCookie(key, '', -1);
  31. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注