第6天-javascript事件

什么是事件

事件是用户在访问页面执行时的操作,也就是用户访问页面时的行为。当浏览器探测到一个事件时,比如鼠标点击或者按键。它可以触发与这个事件相关的JavaScript对象(函数),这些对象成为事件处理程序。

事件函数绑定

事件函数:当事件发生了,用于处理该事件的具体应对方案,表现出来就是一些代码块。例如:当鼠标点击(事件)---做什么操作?就由处理函数来完成

总结:

注意的就是事件发生和事件处理函数是不同的概念

事件发生以后,可以有事件处理函数来做对应的事情,也可以没有

如果没有事件处理函数,不会影响事件的发生,该发生的还是会发生,至于做什么事情,由事件处理函数来决定

<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>

<script>
    oBtn1 = document.getElementById('btn1');
    oBtn2 = document.getElementById('btn2');
    
    oBtn1.onclick = function(){
        alert('hello world');
    }
    
    oBtn2 = null
</script>
事件函数绑定

鼠标事件

onmousedown 当鼠标按下的时候触发
onmouseup 当鼠标抬起的时候触发

 

<div id="box" style="width: 100px; height: 100px; background-color: red;"></div>

<script>
    oBox = document.getElementById('box');
    oBox.onmousedown = function(){
        oBox.style.backgroundColor = 'green';
    };
    
    oBox.onmouseup = function(){
        oBox.style.backgroundColor = 'orange';
    };
</script>
示例
onmouseover 当鼠标移入的时候触发
onmouseout 当鼠标移出的时候触发

 

<style>
    a{    
        padding: 20px;
        text-decoration: none;
        color: black;
    }
</style>

...

<a href="#">首页</a>
<a href="#">产品介绍</a>
<a href="#">关于我们</a>

<script>
    //找到a标签
    aA = document.getElementsByTagName('a');
    //oA是一个数组,遍历出每个a标签
    for(i in aA){
        //鼠标移入事件
        aA[i].onmouseover = function(){
            //如何确定是哪个a标签,可以使用this
            //onsole.log(this)
            this.style.backgroundColor = 'red';
            this.style.color = 'white';
        };
        //鼠标移出事件
        aA[i].onmouseout = function(){
            this.style.backgroundColor = 'white';
            this.style.color = 'black';
        };
    }
</script>
示例
onclick 当鼠标点击的时候触发
ondblclick 当鼠标双击的时候触发
onmousemove 当鼠标移动的时候触发
oncontextmenu  当鼠标右键的时候触发(可以定义右键菜单)

 

<button>按钮</button>

<script>
    //通过标签获取元素,获取到的是一个数组
    oBtn = document.getElementsByTagName('button');
    
    //鼠标双击,因为是数组,所以必须要oBtn加索引才能获取到具体的元素
    oBtn[0].ondblclick = function(){
        alert('鼠标双击了');
    }
    
    //鼠标移动事件
    document.onmousemove = function(){
        console.log('鼠标移动了');
    }
    
    //鼠标右键事件
    document.oncontextmenu = function(){
        alert('右键显示菜单');
        //阻断原来的右击动作
        return false;
    }
</script>
示例

键盘事件

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

 

<script>
    //键盘按下
    document.onkeydown = function(){
        console.log('键盘按下');
        //alert('键盘按下')   这个会阻断事件,导致键盘抬起的动作函数不会执行
    }
    
    document.onkeyup = function(){
        console.log('键盘抬起');
    }        
</script>
示例

那么键盘事件有什么使用场景呢。比如:百度搜索框,当我们输入完关键字,按下回车键后,就会执行搜索

<script>
    //传一个事件参数
    document.onkeydown = function(evt){
        console.log(evt);
    }
</script>
示例

然后我们随便按一个键盘,查看console, 有一项 keyCode(键盘码),每一个按键都有一个唯一的keyCode

我们可以,这样,来按下回车键,查看到回车键的keyCode为13

<script>
    document.onkeydown = function(evt){
        //console.log(evt);
        console.log(evt.keyCode);
    }
</script>
示例

因此,我们可以这样模拟回车搜索

<script>
    //键盘按下
    document.onkeydown = function(evt){
        if(evt.keyCode === 13){
            alert('开始搜索..');
        }
    }
</script>
示例

表单事件

onsubmit  当表单提交的时候触发

<form action="https://www.baidu.com/s">
    <input name="wd" id='ipt' />
    <button type="submit">提交</button>
</form>

<script>
    oForm = document.getElementsByTagName('form');
    oIpt = document.getElementById('ipt');
    oForm[0].onsubmit = function(){
        iptValue = oIpt.value;
        if (iptValue == ''){
            alert('内容不能为空');
            //return flase可以阻止提交
            return false;
        };
        
        return true;    
    };
</script>
示例

onchange 当修改表单字段的时候会触发(内容改变就会触发)

商品单价: <span id="price">198</span> <br/>
商品数量:<input id="ipt1" type="text" value="1" />
商品总价:<input id="ipt2" type="text" value="198">

<script>
    var oIpt1 = document.getElementById('ipt1');
    oIpt1.onchange = function(){
        var price = document.getElementById('price').innerHTML;
        var oIpt2 = document.getElementById("ipt2");
        oIpt2.value = price * this.value;
    };
</script>
示例
<form action="https://www.baidu.com/s" id="fm">
    <input id="ipt" type="text" value="请输入搜索内容" name="wd"/>
</form>

<script>
    var oIpt = document.getElementById('ipt');
    
    //获取焦点事件
    oIpt.onfocus = function(){
        //把输入框内容清空
        oIpt.value = "";
    };
    
    //失去焦点事件
    oIpt.onblur = function(){
        //让输入框内容恢复原样,当用户没有输入内容的时候
        if(oIpt.value == ""){
            oIpt.value = "请输入搜索内容";
        };    
    }
    
    //按回车键表单会自动提交到action设置的地址,浏览器的默认行为
    //当用户没有输入内容的时候,提示不能提交,只有当用户输入内容后才可以提交
    var oForm = document.getElementById("fm");
    oForm.onsubmit = function(){
        if(oIpt.value == ""){
            alert('内容不能为空');
            return false;
        };
    };
</script>
获取焦点和失去焦点事件

窗口事件

onload 当对象加载完成以后触发

要解决这个问题,我们就需要当整个对象加载完再执行,这样就不会报错了

 onresize   当窗口改变的时候的触发

<script>
     window.onresize = function(){
        //窗口改变的时候去计算宽高,来做布局
        //获取浏览器可视区的高端
        console.log(document.documentElement.clientHeight);
        console.log(document.documentElement.clientWidth);
     }
</script>
示例

事件对象 event以及兼容性

事件对象就是当事件发生的时候,用来记录事件的相关信息的对象

<script>
    alert(event);
    window.onload = function(){
        alert(event); //object event
        console.log(event);
    }
    
    //注意 :必须要在事件发生的时候才有值,否则就是undefined
    //兼容性问题
    //    1、在IE和chrome下event对象是内置的,直接使用event就可以了, 在火狐下不支持
    //  2、在火狐和chrome下事件对象是事件处理函数的第一个参数,在ie低版本下不支持
    window.onload = function(evt){
        alert(evt); //object event
        console.log(evt);
    } 
    //如果要解决兼容性,可以这样
    window.onload = function(evt){
        var ev = evt || event;
        alert(ev);
    }
</script>
事件对象及兼容性

event对象上的属性 clientX, clientY

clientX和clientY是鼠标指针在浏览器页面可视区的坐标

<div id="box" style="height: 200px; background-color: orange;"></div>

<script>
    oBox = document.getElementById('box');
    oBox.onclick = function(event){
        console.log('x',event.clientX, 'y',event.clientY);
    }
</script>

 百度登录拖拽效果前置知识-offsetLeft和offsetTop

<style type="text/css">
    #box{
        height: 200px;
        width: 200px;
        background-color: red;
        position: absolute;
        left: 0px;
        top: 30px;
    }
</style>
 
 ...
 
<script>
    //基本思想:要让div移动,可以通过改变left和top值
    //通过js来动态改变
    //条件:需要知道如何获取left值和top值
    oBox = document.getElementById('box');
    oBox.onclick = function(){
        console.log(oBox.offsetLeft, oBox.offsetTop);
    }
</script>

 拖拽效果

 

<style type="text/css">
    #box{
        height: 200px;
        width: 200px;
        background-color: orange;
        position: absolute;
        left: 0;
        top: 0;
    }
</style>

...
<div id="box"></div>
<script>
    var oBox = document.getElementById('box');
    oBox.onmousedown = function(event){
        var difX = event.clientX - oBox.offsetLeft;
        var difY = event.clientY - oBox.offsetTop;
        //鼠标移动
        oBox.onmousemove = function(event){
            oBox.style.left = event.clientX - difX + "px";
            oBox.style.top = event.clientY - difY + "px";
                
        };
        //鼠标抬起后,box不再移动
        oBox.onmouseup = function(){
            oBox.onmousemove = null;
        }
    }
</script>


//这段代码实现了拖拽效果
//但是当快速移动鼠标的时候还有问题,这个后面再解决
拖拽效果代码实现

 事件冒泡机制

当一个元素接收到一个事件以后,会将事件传播给它的父级元素,它的父级元素会一层一层往上传播,直到最顶层的window,这种事件传播机制叫做事件冒泡

<style type="text/css">
        #box1{
            height: 400px;
            width: 400px;
            background-color: green;
            margin: 0 auto;
        }
        
        #box2{
            height: 300px;
            width: 300px;
            background-color: orange;
            margin: 0 auto;
        }
        
        #box3{
            width: 200px;
            height: 200px;
            background-color: red;
            margin: 0 auto;
        }
</style>

...

<script>
    var oBox1 = document.getElementById('box1');
    var oBox2 = document.getElementById('box2');
    var oBox3 = document.getElementById('box3');
    
    function fn(event){
        alert(this.id);
    }
    
    oBox1.onclick = fn;
    oBox2.onclick = fn;
    oBox3.onclick = fn;
    
</script>
示例

当点击div3的时候,先触发div3的点击事件,弹出div3的id值为box3

然后把点击事件传给父级元素div2,触发div2的点击事件,div2绑定了事件处理函数fn,因此会弹出div2的id属性值box2

接着div2再把点击事件传播给div1,div1同样也绑定了事件处理函数,弹出id值为box1

div1再往上传播点击事件,由于div1的父级没有绑定事件处理函数,所以没有弹出值,但是div1的父级还是接收了点击事件,只是没有做出响应

这个就是冒泡机制的全过程,冒泡机制在javascript中是默认存在的

 事件冒泡带来的影响

<style type="text/css">
    #box{
        width: 300px;
        height: 300px;
        background-color: orange;
        display: none;
    }
</style>
...

<button id="btn">显示</button>
<div id="box"></div>

<script>
    var oBtn = document.getElementById('btn');
    var oBox = document.getElementById('box');
    
    //点击按钮显示div, 但是因为冒泡机制,会触发它的父级onclick时间,而document的onclick时间处理函数有把div隐藏
    //因此时间冒泡机制会导致div不能显示出来
    oBtn.onclick = function(){
        oBox.style.display = 'block';
    }
    
    document.onclick = function(){
        oBox.style.display = 'none';
    }
</script>
事件冒泡机制带来的影响
...
<script>
    var oBtn = document.getElementById('btn');
    var oBox = document.getElementById('box');
    
    oBtn.onclick = function(event){
        oBox.style.display = 'block';
        event.stopPropagation(); //阻止冒泡
    }
    
    document.onclick = function(){
        oBox.style.display = 'none';
    }
</script>
阻止事件冒泡

事件冒泡带来的好处

虽然事件冒泡带来了一些不好的影响,但是可以通过取消事件冒泡来解决,之所以默认事件冒泡机制开启,是因为事件冒泡会节省很多代码。例如:有一个需求,点击一个按钮,显示div,点击除按钮外的其他元素,需要隐藏div ,这个时候有两种解决方案。第一种,找到页面中除了按钮外的其他元素,都给这些元素加点击事件,然后隐藏div。这一种如果页面中有几百个元素,那么实现起来就相当复杂,因此不能采用。第二种解决方案,给这些元素的共同父级加点击事件,当这些元素触发点击事件以后,把事件传播给父级元素的点击事件,这样就节省很多代码,也就是上面案例中的应用实现。

 事件源

<ul>
    <li>python</li>
    <li>Java</li>
    <li>Golang</li>
</ul>

<script>
    //我们已经学习过事件冒泡机制
    //现在在li的父级元素配置点击事件,那么子元素li点击就会传播到ul的点击事件
    
    var oUl = document.getElementsByTagName('ul')[0];
    //那么当点击li的时候,我们怎么知道点击了哪个li呢?这就需要用到事件源了event.target
    oUl.onclick = function(event){
        console.log(event.target);
    }
</script>
事件源

下面我们来完成一个小案例,在表单中输入内容,点击添加按钮,会把 表单的内容作为li元素追加到ul中,当点击li的时候,字体变成红色

<input type="text" id="ipt" /> <button id="btn">添加</button>

<ul>
    <li>Python</li>
    <li>Java</li>
    <li>Golang</li>
</ul>

<script>
    //找到input元素
    var oInput= document.getElementById('ipt');
    //找到按钮
    var oBtn = document.getElementById('btn');
    
    //找到ul
    oUl = document.getElementsByTagName('ul')[0];
    
    //找到li,注意这里获取到的是个数组
    var oLis = document.getElementsByTagName('li');
    
    //按钮点击事件
    oBtn.onclick = function(){
        //获取input的值
        var oInputvalue = oInput.value;
        //如果值为空则弹窗提示不能为空
        if(oInputvalue == ""){
            alert('值不能为空!');
            return  false;
        }
        
        //创建一个li元素
        var oLi = document.createElement('li');
        //li里面的内容为 input的值
        oLi.innerHTML = oInputvalue;
        //把这个li加入到ul中
        oUl.appendChild(oLi);
    }
    
    //设置li的点击事件,字体变为红色
    for(var i=0;i<oLis.length;i++){
        oLis[i].onclick = function(){
            this.style.color = "red";
        }
    }        
</script>
方案1

这是为什么呢?

这是因为先执行了循环,只有3个值,因为前面的3个可以正常变色。那么这种情况下,我们就可以不用循环,利用冒泡机制来解决

把点击事件放在li的父级元素ul上(因为冒泡机制,点击li会传播到ul),然后根据事件源能够做到点击了哪个li,然后把它的字体变色

//设置ul的点击事件
oUl.onclick = function(event){
    event.target.style.color = "red";
}

 

前面我们还遗留了一个拖拽效果,速度变快出现 bug的问题,那是因为移动过快导致鼠标已经移出了div,从而导致oBox.onmousemove事件没有发生了。这个问题也可以通过冒泡机制解决,我们只要把鼠标按下,移动,抬起的事件绑定到它的父级元素document就可以了

posted @ 2018-10-17 22:01  sellsa  阅读(186)  评论(0编辑  收藏  举报