03-2-JavaScript基础之Web API(DOM)

1. Web API


Web API介绍


API概念

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

  • 任何开发语言都有自己的API
  • API的特征输入和输出(I/O)
    • var max = Math.max(1, 2, 3);
  • API的使用方法(console.log(‘adf’))

Web API的概念

浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)

此处的Web API特指浏览器提供的API(一组方法),Web API在后面的课程中有其它含义

掌握常见浏览器提供的API的调用方式

MDN


JavaScript的组成(重点理解)
03-2-JavaScript基础之Web API(DOM)_第1张图片

  • ECMAScript - JavaScript的核心

定义了JavaScript 的语法规范

JavaScript的核心,描述了语言的基本语法和数据类型,ECMAScript是一套标准,定义了一种语言的标准与具体实现无关

  • BOM - 浏览器对象模型

一套操作浏览器功能的API

通过BOM可以操作浏览器窗口,比如:弹出框、控制浏览器跳转、获取分辨率等

  • DOM - 文档对象模型

一套操作页面元素的API

DOM可以把HTML看做是文档树,通过DOM提供的API可以对树上的节点进行操作

2. DOM


DOM的概念

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和www文档的风格(目前,HTML和XML文档是通过说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM是一种基于树的API文档,它要求在处理过程中整个文档都表示在存储器中。

DOM又称为文档树模型

03-2-JavaScript基础之Web API(DOM)_第2张图片

  • 文档:一个网页可以称为文档
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
  • 元素:网页中的标签
  • 属性:标签的属性

DOM经常进行的操作

  • 获取元素
  • 对元素进行操作(设置其属性或调用其方法)
  • 动态创建元素
  • 事件(什么时机做相应的操作)

3. 获取页面元素


为什么要获取页面元素

例如:我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,才进行后续操作

根据id获取元素

var div = document.getElementById('main');
console.log(div);

// 获取到的数据类型 HTMLDivElement,对象都是有类型的

注意:由于id名具有唯一性,部分浏览器支持直接使用id名访问元素,但不是标准方式,不推荐使用。

根据标签名获取元素

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  var div = divs[i];
  console.log(div);
} 

根据name获取元素*

var inputs = document.getElementsByName('hobby');
for (var i = 0; i < inputs.length; i++) {
  var input = inputs[i];
  console.log(input);
}

根据类名获取元素*

var mains = document.getElementsByClassName('main');
for (var i = 0; i < mains.length; i++) {
  var main = mains[i];
  console.log(main);
}

根据选择器获取元素*

var text = document.querySelector('#text');
console.log(text);

var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
  var box = boxes[i];
  console.log(box);
}

总结

掌握
	getElementById()
	getElementsByTagName()
了解
	getElementsByName()
	getElementsByClassName()
	querySelector()
	querySelectorAll()

4. 事件


事件:触发-响应机制

事件三要素

  • 事件源:触发(被)事件的元素
  • 事件名称: click 点击事件
  • 事件处理程序:事件触发后要执行的代码(函数形式)

事件的基本使用

var box = document.getElementById('box');
box.onclick = function() {
  console.log('代码会在box被点击后执行');  
};

案例

// 点击按钮弹出提示框
        btn = document.getElementById('btn');
        // 给按钮注册事件
        btn.onclick = function () {
            alert('点我了');
        }
// 点击按钮切换图片
// 获取元素
        var btn = document.getElementById('btn');
        var mv = document.getElementById('mv');
        var flag = 1;
        // 注册按钮事件
        btn.onclick = function () {
            // 切换图片
            if (flag === 1) {
                mv.src = 'images/b.jpg';
                flag = 2;
            } else {
                mv.src = 'images/a.jpg';
                flag = 1;
            }
            
        }

5. 属性操作



5.1 非表单元素的属性


  • href、title、id、src、className
var link = document.getElementById('link');
console.log(link.href);
console.log(link.title);

var pic = document.getElementById('pic');
console.log(pic.src);

案例

// 点击按钮显示隐藏div
// 获取元素
        var btn = document.getElementById('btn');
        var box = document.getElementById('box');
        var flag = 1;
        // 注册事件
        btn.onclick = function () {
            // 控制显示隐藏
            if (flag === 1) {
                this.value = '显示';
                box.className = 'hidden';
                flag = 2;
            } else {
                this.value = '隐藏';
                box.className = 'block';
                flag = 1;
            }
        }

美女相册案例HTML


<h2>美女画廊h2>

    <div id="imagegallery">
        <a href="images/1.jpg" title="美女A">
            <img src="images/1-small.jpg" width="100" alt="美女1">
        a>
        <a href="images/2.jpg" title="美女B">
            <img src="images/2-small.jpg" width="100" alt="美女2">
        a>
        <a href="images/3.jpg" title="美女C">
            <img src="images/3-small.jpg" width="100" alt="美女3">
        a>
        <a href="images/4.jpg" title="美女D">
            <img src="images/4-small.jpg" width="100" alt="美女4">
        a>
    div>

    <div style="clear: both">div>

    <img id="image" src="images/placeholder.png" alt="" width="450">

    <p id="des">选择一个图片p>

美女相册案例JS

// 1 获取到所有的a标签
    var imagegallery = document.getElementById('imagegallery');
    var links = imagegallery.getElementsByTagName('a');
    // 2 给所有的a标签注册事件
    for (var i = 0; i < links.length; i++) {
            var link = links[i];
        link.onclick = function () {
            
            // 4 切换图片
            //   获取占位大的img
            var image = document.getElementById('image');
            //   把img标签的属性 设置为点前点击a的标签的href
            image.src = this.href;

            // 5 设置p标签的内容
            var des = document.getElementById('des');
            // link 中的 title  
            // 设置 p  中的内容
            // console.dir(des)
            des.innerHTML = this.title;

            // 3 取消a 的默认注册事件
            return false;
        }
    }
  • innerHTML和innerText
var box = document.getElementById('box');
box.innerHTML = '我是文本

我会生成为标签

'
; console.log(box.innerHTML); box.innerText = '我是文本

我不会生成为标签

'
; console.log(box.innerText);
  • HTML转义符
"		&quot;
'		&apos;
&		&amp;
<		&lt;   // less than  小于
>		&gt;   // greater than  大于
空格	   &nbsp;
©		&copy;
  • innerHTML和innerText的区别
// 内容标签,以 HTML 形式显示出来
box.innerHTML = "黑马程序员";
// 原封不动的显示出来
box.innerText = '黑马程序员';
  • innerText的兼容性处理
// 如何知道 浏览器是否支持元素的某个属性
    var box = document.getElementById('box');

    console.log(getInnerText(box));
    // 当属性不存在的时候 返回的是 undefined
    function getInnerText(element) {
        if (typeof element.innerText === 'string') {
            return element.innerText;
        } else {
            return element.textContent;
        }
    }

5.2 表单元素属性


  • value 用于大部分表单元素的内容获取(option除外)
  • type 可以获取input标签的类型(输入框或复选框等)
  • disabled 禁用属性
  • checked 复选框选中属性
  • selected 下拉菜单选中属性

案例

  • 点击按钮禁用文本框
// 获取元素
        var btn = document.getElementById('btn');
        var txt = document.getElementById('txt');
        // 注册点击事件
        btn.onclick = function () {
            console.log(txt.value);
            console.log(txt.type);
            // 当 html 中的标签的属性只有一个的时候
            // 在 DOM 中的类型为 布尔类型
            console.log(txt.disabled)
            txt.disabled = true;	// 禁用,默认为false
        }
  • 给文本框赋值,获取文本框的值
// 获取所有文本框的值
      var inputs = document.getElementsByTagName('input');
      for (var i = 0; i < inputs.length; i++) {
          var input = inputs[i];
          // 判断是否是文本框
          if (input.type === 'text') {
              input.value = i;
          }
      }
      // 点击按钮,获取所有文本框的值并使用 | 分割输出
     var btn = document.getElementById('btn');
        btn.onclick = function () {
            var array = [];
            for (var i = 0; i < inputs.length; i++) {
                var input = inputs[i];
                // 判断是否是文本框
                if (input.type === 'text') {
                    array.push(input.value);
                }
                
            }
            // 拼接
            var s = array.join('|');
            console.log(s)
        } 
  • 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框
// 检测用户名是否是 3-6 位,密码是 6-8 位,如果不满足要求高亮显示文本框
var btnLogin = document.getElementById('btnLogin');

btnLogin.onclick = function () {
    // 检测用户名是否是 3-6 位,密码是 6-8 位
    var txtUserName = document.getElementById('txtUserName');
    var  txtUserPassword = document.getElementById('txtUserPassword');

    // 检测用户名是否是 3-6 位
    if (txtUserName.value.length < 3 || txtUserName.value.length > 6) {
        txtUserName.className = 'bg';
        return;
    } else {
        txtUserName.className = '';
    }

    // 密码是 6-8 位
    if (txtUserPassword.value.length < 6 || txtUserPassword.value.length > 8) {
        txtUserPassword.className = 'bg';
        return;
    } else {
        txtUserPassword.className = '';
    }

    console.log('执行登陆')
}
  • 设置下拉框中的选中项
// 1 给按钮注册事件
var btnSet = document.getElementById('btnSet');
btnSet.onclick = function () {
    // 2 获取下拉框的所有option
    var selCities = document.getElementById('selCities');
    var options = selCities.getElementsByTagName('option');
    // 3 随机生成索引
    // Math.random()  ->  [0, 1)
    // Math.random() * 5  ->  [0, 5)
    var randomIndex = parseInt(Math.random() * options.length);
    // 4 根据索引获取 oprion,并让 option 选中
    var option = options[randomIndex];
    option.selected = true;
}
  • 搜索文本框
// 当文本框获得焦点,如果文本框的内容是 请输入搜索关键字 清空文本框并让字体变黑色
// 当文本框是去焦点,如果文本框里的内容为空,还原文本框里的文字,并让字体变为灰色
var txtSearch = document.getElementById('txtSearch');
// 获取焦点的时间 focus
txtSearch.onfocus = function () {
    if (this.value === '请输入搜索关键字') {
        this.value = '';
        this.className = 'black';
    }
}
// 当文本框是去焦点,如果文本框里的内容为空,还原文本框的文字,并让文字变为灰色
txtSearch.onblur = function () {
    if (this.value.length === 0 || this.value === '请输入搜索关键字') {
        this.value = '请输入搜索关键字';
        this.className = 'gray';
    }
}
  • 全选反选
// 全选功能
// 获取父checkbox,注册点击事件
var j_cbAll = document.getElementById('j_cbAll');
var j_tb = document.getElementById('j_tb');
var inputs = j_tb.getElementsByTagName('input');
j_cbAll.onclick = function () {
    for ( var i = 0; i < inputs.length; i++) {
        input = inputs[i];
        if ( input.type === 'checkbox') {
            input.checked = this.checked;
        }
    }
}
// 2 当点击子的checkbox,如果所有的子的checkbox都被选中了,父的checkbox也被选中
// 如果有一个子的checkbox 没有被选中,父的checkbox也不被选中
for( var i = 0; i < inputs.length; i++) {
    input = inputs[i];
    // 判断是否是 checkbox
    if (input.type !== 'checkbox') {
        continue;
    } 
    input.onclick = function () {
        checkAllCheckbox();
    }
    
}

function checkAllCheckbox() {
    // 判断所有的子的checkbox都被选中
    var isAllChecked = true;
        for( var i = 0; i < inputs.length; i++) {
            input = inputs[i];
            if(!input.checked) {
                isAllChecked = false;
            }
        }
        j_cbAll.checked = isAllChecked;
}
// 3 反选
// 给反选按钮点击事件
var btn = document.getElementById('btn');
btn.onclick = function () {
    for (var i = 0; i < inputs.length; i++) {
        input = inputs[i];
        if (input.type !== 'checkbox') {
            continue;
        }
        var input = inputs[i];
        input.checked = !input.checked;
    }
    // 判断父的checkbox
    checkAllCheckbox();
}

5.3 自定义属性操作


  • getAttribute() 获取标签行内属性
  • setAttribute() 设置标签行内属性
  • removeAttribute() 移除标签行内属性
  • 与element.属性的区别: 上述三个方法用于获取任意的行内属性。

5.4 样式操作


使用style方式设置的样式显示在标签行内

var box = document.getElementById('box');
box.style.width = '100px';
box.style.height = '100px';
box.style.backgroundColor = 'red';

注意
通过样式属性设置宽高、位置的属性类型是字符串,需要加上px

5.5 类名操作


修改标签的className属性相当于直接修改标签的类名

var box = document.getElementById('box');
box.className = 'show';

案例

  • 开关灯
// 是否开灯  false 关灯状态  true 开灯状态
    var isOpen = true;
    document.getElementById('btn').onclick = function () {
      if (isOpen) {
        document.body.style.backgroundColor = 'black';
        this.value = '开灯';
        isOpen = false;
      } else {
        document.body.style.backgroundColor = 'white';
        this.value = '关灯';
        isOpen = true;
      }
    }
  • 点击按钮改变div的背景颜色
	document.getElementById('btn').onclick = function () {
      // 当设置宽度和高度的时候必须带单位,如果不带单位,有错误
      var box = my$('box');
      box.style.width = '200px';
      box.style.height = '200px';
      box.style.backgroundColor = 'red';
    }
  • 图片切换二维码案例
// 当鼠标移入  onmouseover
// 当鼠标移出  onmouseout
var nodeSmall = document.getElementById('node_small');
nodeSmall.onmouseover = function () {
    // my$('er').className = 'erweima show';
    my$('er').className = my$('er').className.replace('hide', 'show'); 
}


nodeSmall.onmouseout = function () {
    // my$('er').className = 'erweima hide';
    my$('er').className = my$('er').className.replace('show', 'hide');
}
  • 当前输入的文本框高亮显示
var inputs = document.getElementsByTagName('input');
    for (var i = 0; i < inputs.length; i++) {
      var input = inputs[i];
      // 判断input是否是文本框
      if (input.type !== 'text') {
        continue;
      } 
      // 让当前正在输入的文本框 高亮显示
      input.onfocus = function () {
        // 让所有的文本框去掉高亮的效果
         for (var i = 0; i < inputs.length; i++) {
           var input = inputs[i];
           if (input.type !== 'text') {
             continue;
           }
           // 去除所有文本框高亮显示
           input.style.backgroundColor = '';
         }
        
        // 当前文本框高亮显示
        this.style.backgroundColor = 'lightgray';
        
      }
    }
  • 点击按钮改变div的大小和位置
document.getElementById('btn').onclick = function () {
      var box = my$('box');
      // 使用style  设置大小和位置的时候 数字必须带单位
      box.style.width = '200px';
      box.style.height = '200px';
      
      box.style.position = 'absolute';
      box.style.left = '200px';
      box.style.top = '200px';
    }
  • 列表隔行变色、高亮显示
// 1 隔行变色
// 获取到所有的li,判断奇数行和偶数行
var mv = document.getElementById('mv');
var lists = mv.getElementsByTagName('li');

for (var i = 0; i < lists.length; i++) {
  var li = lists[i];
  // 判断当前的li 是奇数行 还是偶数行
  if (i % 2 === 0) {
    // i是偶数 , 但是当前是奇数行
    // 设置奇数行的背景颜色
    li.style.backgroundColor = 'red';
  } else {
    // 设置偶数行的背景颜色
    li.style.backgroundColor = 'green';
  }
}
   
// 2 鼠标放上高亮显示
// 2.0 给所有的li 注册事件  鼠标经过和鼠标离开的两个事件
for (var i = 0; i < lists.length; i++) {
  var li = lists[i];
   // 2.1 鼠标放到li上,高亮显示当前的li
   var bg;
   li.onmouseover = function () {
     // 鼠标放到li上的时候,应该记录li当前的颜色
     bg = this.style.backgroundColor;

     this.style.backgroundColor = 'yellow';
   }
   // 2.2 鼠标离开li,还原原来的颜色
   li.onmouseout = function () {
     // 鼠标离开,还原原来的颜色
     this.style.backgroundColor = bg;
   }
}
  • tab选项卡切换
// 1 鼠标放到tab栏高亮显示,其它tab栏取消高亮
var hd = my$('hd');
var spans = hd.getElementsByTagName('span');
for (var i = 0; i < spans.length; i++) {
    var span = spans[i];
    // 通过自定义属性,记录当前span的索引
    span.setAttribute('index', i);
    // 注册事件
    span.onmouseover = fn
}

// 鼠标经过的事件处理函数
function fn() {
    // 让所有的span取消高亮显示
    for (var i = 0; i < spans.length; i++) {
        var span = spans[i];
        span.className = '';
    }
    // 当前的span高亮显示
    this.className = 'current';

    // 2 tab栏对应的div 显示,其它div隐藏
    // 所有的div 隐藏
    var bd = my$('bd');
    var divs = bd.getElementsByTagName('div');
    for (var i = 0; i < divs.length; i++) {
        var div = divs[i];
        div.className = '';
    }
    // 当前span对应的div显示
    // 获取自定义属性的值
    var index = parseInt(this.getAttribute('index')) ;
    divs[index].className = 'current';
    
}

6. 创建元素的三种方式


document.write()

document.write('新设置的内容

标签也可以生成

'
);

innerHTML

var box = document.getElementById('box');
box.innerHTML = '新内容

新标签

'
;

document.createElement()

var div = document.createElement('div');
document.body.appendChild(div);

性能问题

  • innerHTML方法由于会对字符串进行解析,需要避免在循环内多次使用。
  • 可以借助字符串或数组的方式进行替换,再设置给innerHTML
  • 优化后与document.createElement性能相近

案例:

动态创建列表,高亮显示

//动态创建列表,高亮显示
var datas = ['西施', '貂蝉', '凤姐', '芙蓉姐姐'];
        // 点击按钮 动态创建列表 鼠标放上高亮显示
        my$('btn').onclick = function () {
            // 动态创建ul
            var ul = document.createElement('ul');
            my$('box').appendChild(ul);

            for (i = 0; i < datas.length; i++) {
                var li = document.createElement('li');
                ul.appendChild(li);

                // 设置li中的显示的内容
                // innerText
                // li.innerText = datas[i];
                setInnerText(li, datas[i]);

                // 给 li 注册事件
                li.onmousemove = liMouseOver;
                li.onmouseout = liMouseOut;
            }
        }

        function liMouseOver() {
            // 鼠标经过高亮显示
            this.style.backgroundColor = 'red';
        }
        function liMouseOut() {
            this.style.backgroundColor = '';
        }

        // 设置标签之间的内容
        function setInnerText(element, content) {
            // 判断当前浏览器是否支持 innerText
            if (typeof element.innerText === 'string') {
                element.innerText = content;
            } else {
                element.textContent = content;
            }
        }

根据数据动态创建表格

// var s = {name: 'zs', subject: '语文', score: 90};
        // 模拟数据
        var datas = [
            {name: 'zs', subject: '语文', score: 90},
            {name: 'zs2', subject: '语文2', score: 90},
            {name: 'zs3', subject: '语文3', score: 90},
            {name: 'zs4', subject: '语文4', score: 90},
            {name: 'zs5', subject: '语文5', score: 90},
            {name: 'zs6', subject: '语文6', score: 90},
        ]; 
        
        // 表头数据
        var headDate = ['姓名', '科目', '成绩', '操作'];

        // 1 创建表格
        var table = document.createElement('table');
        my$('box').appendChild(table);
        table.border = '1px';
        table.width = '400px';
        // 2 创建表头
        var thead = document.createElement('thead');
        table.appendChild(thead);

        var tr = document.createElement('tr');
        thead.appendChild(tr);
        tr.style.height = '40px';
        tr.style.backgroundColor = 'lightgray';

        for (var i = 0; i < headDate.length; i++) {
            var th = document.createElement('th');
            tr.appendChild(th);
            // th.innerText
            setInnerText(th, headDate[i]);
        }
        
        var tbody = document.createElement('tbody');
        tbody.style.textAlign = 'center';
        table.appendChild(tbody);
        for (var i = 0; i < datas.length; i++) {
            // {name: 'zs', subject: '语文', score: 90},
            var tr = document.createElement('tr');
            tbody.appendChild(tr);

            var data = datas[i];
            for ( var key in data) {
                var td = document.createElement('td');
                tr.appendChild(td);
                setInnerText(td, data[key]);
            }
            // 生成删除对应的列

            var td = document.createElement('td');
            tr.appendChild(td);

            var link = document.createElement('a');
            td.appendChild(link);
            link.href = 'javascript:void(0)';
            setInnerText(link, '删除');

            link.onclick = linkDelete;
            
        }

        function linkDelete() {
            // removeChild
            // 获取父元素
            var tr = this.parentNode.parentNode;
            tbody.removeChild(tr);     
            return false;
        }

7. 节点操作


var body = document.body;
var div = document.createElement('div');
body.appendChild(div);

var firstEle = body.children[0];
body.insertBefore(div, firstEle);

body.removeChild(firstEle);

var text = document.createElement('p');
body.replaceChild(text, div);

案例:

选择水果

var all = my$('all');
var select = my$('select');
// 1 全部选择
  my$('btn1').onclick = function () {
      // 移走 children 索引会变化
      //for (var i = 0; i < all.children.length; i++) {
      //    select.appendChild(all.children[i]);
      //}
      //for (var i = all.children.length -1; i >= 0; i--) {
      //    select.appendChild(all.children[i]);
      //}
      var len = all.children.length;
      for (var i = 0; i < len; i++) {
           select.appendChild(all.children[0]);
      }
  }

  // 2 移动选中的水果
  my$('btn3').onclick = function () {
      // 找到所有选中的option
      var array = []; // 存储选中的option
      for (var i = 0; i < all.children.length; i++) {
          var option = all.children[i];
          if (option.selected) {
              array.push(option);
              option.selected = false;
          }
      }

      // 把数组的option移动到第二个select
      for ( var i = 0; i < array.length; i++) {
          select.appendChild(array[i]);
      }
  }

节点属性

  • nodeType 节点的类型
    • 1 元素节点
    • 2 属性节点
    • 3 文本节点
  • nodeName 节点的名称(标签名称)
  • nodeValue 节点值
    • 元素节点的nodeValue始终是null

模拟文档树结构

03-2-JavaScript基础之Web API(DOM)_第3张图片

function Node(option) {
  this.id = option.id || '';
  this.nodeName = option.nodeName || '';
  this.nodeValue = option.nodeValue || '';
  this.nodeType = 1;
  this.children = option.children || [];
}

var doc = new Node({
  nodeName: 'html'
});
var head = new Node({
  nodeName: 'head'
});
var body = new Node({
  nodeName: 'body'
})
doc.children.push(head);
doc.children.push(body);

var div = new Node({
  nodeName: 'div',
  nodeValue: 'haha',
});

var p = new Node({
  nodeName: 'p',
  nodeValue: '段落'
})
body.children.push(div);
body.children.push(p);

function getChildren(ele) {
  for(var i = 0; i < ele.children.length; i++) {
    var child = ele.children[i];
    console.log(child.nodeName);
    getChildren(child);
  }
}
getChildren(doc);

节点层级

03-2-JavaScript基础之Web API(DOM)_第4张图片

var box = document.getElementById('box');
console.log(box.parentNode);
console.log(box.childNodes);
console.log(box.children);
console.log(box.nextSibling);
console.log(box.previousSibling);
console.log(box.firstChild);
console.log(box.lastChild);
  • 注意
    childNodes和children的区别,childNodes获取的是子节点,children获取的是子元素
    nextSibling和previousSibling获取的是节点,获取元素对应的属性是nextElementSibling和previousElementSibling获取的是元素
    nextElementSibling和previousElementSibling有兼容性问题,IE9以后才支持
  • 总结
节点操作,方法
	appendChild()
	insertBefore()
	removeChild()
	replaceChild()
节点层次,属性
	parentNode
	childNodes
	children
	nextSibling/previousSibling
	firstChild/lastChild

8. 事件详解


注册/移除事件的三种方式

var box = document.getElementById('box');
box.onclick = function () {
  console.log('点击后执行');
};
box.onclick = null;

box.addEventListener('click', eventCode, false);
box.removeEventListener('click', eventCode, false);

box.attachEvent('onclick', eventCode);
box.detachEvent('onclick', eventCode);

function eventCode() {
  console.log('点击后执行');
}

兼容代码

function addEventListener(element, type, fn) {
  if (element.addEventListener) {
    element.addEventListener(type, fn, false);
  } else if (element.attachEvent){
    element.attachEvent('on' + type,fn);
  } else {
    element['on' + type] = fn;
  }
}

function removeEventListener(element, type, fn) {
  if (element.removeEventListener) {
    element.removeEventListener(type, fn, false);
  } else if (element.detachEvent) {
    element.detachEvent('on' + type, fn);
  } else {
    element['on'+type] = null;
  }
}

事件的三个阶段

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段
    事件对象.eventPhase属性可以查看事件触发时所处的阶段

事件对象的属性和方法

  • event.type 获取事件类型
  • clientX/clientY 所有浏览器都支持,窗口位置
  • pageX/pageY IE8以前不支持,页面位置
  • event.target || event.srcElement 用于获取触发事件的元素
  • event.preventDefault() 取消默认行为

案例

  • 跟着鼠标飞的天使
var ts = document.getElementById('ts');
   document.onmousemove = function (e) {
       e = e || window.event;
       // ts.style.left = e.clientX -10 + 'px';
       // ts.style.top = e.clientY -10 + 'px';

       ts.style.left = e.pageX -10 + 'px';
       ts.style.top = e.pageY -10 + 'px';
   }
  • 获取鼠标在div内的坐标
var box = document.getElementById('box');
    box.onclick = function (e) {
        // 获取盒子在页面的位置
        // console.log(this.offsetLeft);
        // console.log(this.offsetTop);

        e = e || window.event;
        // 获取鼠标在盒子中的位置
        var x = getPage(e).pageX - this.offsetLeft;
        var y = getPage(e).pageY - this.offsetTop;
        console.log(x + ',' + y)
    }
    
    function getPage(e) {
	    var pageX = e.pageX || e.clientX + getScroll().scrollLeft;
	    var pageY = e.pageY || e.clientY + getScroll().scrollTop;
	    return {
	        pageX: pageX,
	        pageY: pageY
	    }
	}

阻止事件传播的方式

  • 标准方式 event.stopPropagation();
  • IE低版本 event.cancelBubble = true; 标准中已废弃

常用的鼠标和键盘事件

  • onmouseup 鼠标按键放开时触发
  • onmousedown 鼠标按键按下触发
  • onmousemove 鼠标移动触发
  • onkeyup 键盘按键按下触发
  • onkeydown 键盘按键抬起触发



加油加油加油,冲鸭冲鸭冲鸭~~~

你可能感兴趣的:(03-2-JavaScript基础之Web API(DOM))