zoukankan      html  css  js  c++  java
  • Web APIs---8. DOM事件高级(3)

    5 阻止事件冒泡

    5.1 阻止事件冒泡的两种方式

    事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点。事件冒泡本身的特性会带来坏处也会带来好处。

    阻止事件冒泡
    • 标准写法:利用事件对象里面的stopPropagation()方法
    e.stopPropagation()
    
    • 非标准写法:IE6-8利用事件对象cancleBubble属性
    e.cancelBubble = true;
    
    • 兼容性写法
    //3. 兼容性方案
    if (e && e.stopPropagation) {
        e.stopPropagation();
    } else {
        window.event.cancelBubble = true;
    }
    
    • 举例:
    <body>
        <div class="father">
            <div class="son">son盒子</div>
        </div>
        <script>
            // 冒泡阶段:document<-html<-body<-father<-son 
            var son = document.querySelector('.son');
            son.addEventListener('click', function(e) {
                alert('son');
    
                //阻止冒泡   dom推荐的标准stopPropagation
                //1.
                e.stopPropagation(); //这样点击son之后只会弹出son这一个对话框,不会再弹出father和document
                //2.
                e.cancelBubble = true; //非标准写法 低版本浏览器
                //3. 兼容性方案
                if (e && e.stopPropagation) {
                    e.stopPropagation();
                } else {
                    window.event.cancelBubble = true;
                }
            }, false);
            //注意上述代码只是阻止点击son时出现的冒泡,若是点击father还是会出现冒泡,所有还要将上述代码放到father中
    
            var father = document.querySelector('.father');
            father.addEventListener('click', function() {
                alert('father');
            }, false);
    
            document.addEventListener('click', function() {
                alert('document');
            })
        </script>
    </body>
    

    6 事件委托(代理、委派)

    事件冒泡本身的特性会带来坏处也会带来好处,需要灵活掌握。生活中有如下场景:

    • 生活中

    • 程序中

    事件委托

    事件委托也称为事件代理,在jQuery里面称为事件委派

    事件委托的原理

    不是每个子节点都单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
    以上案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件就会冒泡到ul上,ul有注册事件就会触发事件监听器

    事件委托的作用

    我们只操作了一次DOM,提高了程序的性能

    • 举例:
    <body>
        <ul>
            <li>知否知否,点我应有弹框在手!</li>
            <li>知否知否,点我应有弹框在手!</li>
            <li>知否知否,点我应有弹框在手!</li>
            <li>知否知否,点我应有弹框在手!</li>
            <li>知否知否,点我应有弹框在手!</li>
        </ul>
        <script>
            //点击一个小li就会弹出一个对话框,之后这个被点击的小li就会变成粉色
            var ul = document.querySelector('ul');
            ul.addEventListener('click', function(e) {
                alert('知否知否,点我应有弹框在手!'); //这样点击任何一个小li都会弹出这句话
                e.target.style.backgroundColor = 'pink';
            })
        </script>
    </body>
    
    //冒泡:点击了哪个盒子就从哪个盒子开始检查执行
    //点击了li; 那么就从li开始检查执行:检查发现li没有绑定click,那么就继续冒泡到ul; 对ul进行检查执行:检查发现绑定了click,就调用对应的事件处理程序; 之后继续冒泡。。。
    

    7 常用的鼠标事件

    7.1 常用的鼠标事件

    禁止鼠标右键菜单contextmenu

    事件contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

    document.addEventListener('contextmenu', function(e){
        e.preventDefault();
    })
    
    • 举例:
    <body>
        我是一段不愿意分享的文字
        <script>
            //1. contextmenu
            document.addEventListener('contextmenu', function(e) {
                e.preventDefault();
            })
        </script>
    </body>
    
    禁止鼠标选中(selectstart 开始选中)
    document.addEventListener('selectstart', function(e){
        e.preventDefault();
    })
    
    • 举例
    <body>
        我是一段不愿意分享的文字
        <script>
            //2. selectstart
            document.addEventListener('selectstart', function(e) {
                e.preventDefault();
            })
        </script>
    </body>
    

    7.2 鼠标事件对象

    event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent和KeybordEvent。

    <body>
        <script>
            //鼠标事件对象MouseEvent
            document.addEventListener('click', function(e) {
                console.log(e);
                //client是相对于可视区,无论body有多长,无论怎么拖动滚动条
                console.log(e.clientX);
                console.log(e.clientY);
                //page鼠标在页面文档中的x和y坐标  支持ie9+
                console.log(e.pageX);
                console.log(e.pageY);
                //screen鼠标在电脑屏幕的x和y(不常用)
                console.log(e.screenX);
                console.log(e.screenY);
            })
        </script>
    </body>
    
    <style>
        body {
            height: 3000px;
        }
    </style>
    
    案例:跟随鼠标移动的天使

    • 鼠标不断移动,使用鼠标移动事件:mousemove
    • 在页面中移动,给document注册事件
    • 图片要移动距离,而且不占位置,我们使用绝对定位即可
    • 核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标,把这个x和y坐标作为图片的top和left就可以移动图片
    <body>
        <img src="images/angel.gif" alt="">
        <script>
            var pic = document.querySelector('img');
            document.addEventListener('mousemove', function(e) { //只要移动鼠标就会触发这个事件
                var x = e.pageX;//返回的是数字型的,不是带'px'的字符串
                var y = e.pageY;
                //鼠标在图片左上角
                // pic.style.left = x + 'px';
                // pic.style.top = y + 'px';
                //鼠标在图片中间  图片宽度是79px * 68px
                pic.style.left = x - 40 + 'px';
                pic.style.top = y - 34 + 'px';
            })
        </script>
    </body>
    
    <style>
        img {
            position: absolute;
        }
    </style>
    

    8 常用的键盘事件

    8.1 常用键盘事件 keyup/keydown/keypress(keypress不识别功能键)

    按下一个键再松开后,上面这三个事件的执行顺序是:keydown--->keypress--->keyup

    • 举例
    <body>
        <script>
            //keyup传统
            // document.onkeyup = function() {
            //         console.log("我弹起来了");
            //     }
    
            //现在推荐写法
            //keyup
            document.addEventListener('keyup', function() {
                console.log('我弹起来了');
            })
    
            //keydown  若按着不松手则会一直触发
            document.addEventListener('keydown', function() {
                console.log('我按下了down');
            })
    
            //keypress  若按着不松手则会一直触发
            document.addEventListener('keypress', function() {
                console.log('我按下了press');
    
            })
        </script>
    </body>
    

    8.1 键盘事件对象keyCode

    • keyCode这个属性对于keyup和keydown是不识别大小写的,均返回大写字母的ASCII
    • 对于keypress是识别大小写的,返回不同的ASCII。
    <body>
        <script>
            //键盘事件对象中的keyCode属性可以得到相应的ASCII码值
            document.addEventListener('keyup', function(e) {
                console.log(e);
                console.log(e.key); //1【虽然这个1可以被直接读出,但是很多浏览器不认识这个属性】
                console.log(e.keyCode); //49【是1的ASCII】
                //可以利用keycode返回的ASCII值来判断用户按下了哪个键
                if (e.keyCode === 65) {
                    alert('您按下的是a键');
                } else {
                    alert('您没有按下a键');
                }
            })
    
    
            //1. keyup和keydown事件不区分字母大小写 a和A得到的ASCII都是65【A】
            //2. keypress区分字母大小写
            document.addEventListener('keypress', function(e) {
                console.log(e);
                console.log(e.key); //a
                console.log('press' + e.keyCode); //97
            })
        </script>
    </body>
    

    案例:模拟京东按键输入内容【当我们按下S键,光标就定位到搜索框】

    思路分析:

    • 检测用户是否按下了S键,如果按下了s键,就把光标定位到搜索框里面
    • 使用键盘事件对象里面的keyCode判断用户是否按下了s键
    • 搜索框获得焦点:使用js里面的focus()方法
    <body>
        <input type="text">
        <script>
            var search = document.querySelector('input');
            document.addEventListener('keyup', function(e) { //若用keydown则键盘按下之后会一直触发,导致来不及松开导致s被写入搜索框中
                if (e.keyCode === 83) { //S的ASCII是83
                    search.focus(); //搜索框获得焦点
                }
            })
        </script>
    </body>
    

    案例:模拟京东快递单号查询

    要求:当我们在文本框中输入内容时,文本框上面自动显示大字号的内容

    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .search {
            position: relative;
             178px;
            margin: 100px;
        }
        
        .con {
            display: none;
            /*先把这个盒子隐藏起来*/
            position: absolute;
            top: -40px;
             171px;
            border: 1px solid rgba(0, 0, 0, .2);
            box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
            padding: 5px 0;
            font-size: 18px;
            line-height: 20px;
            color: #333;
        }
        
        .con::before {
            content: '';
             0;
            height: 0;
            position: absolute;
            top: 28px;
            left: 18px;
            border: 8px solid #000;
            border-style: solid dashed dashed;
            border-color: #fff transparent transparent;
        }
    </style>
    
    <body>
        <div class="search">
            <div class="con">123</div>
            <input type="text" placeholder="请输入您的快递单号" class="jd">
            <script>
                var con = document.querySelector('.con');
                var jd_input = document.querySelector('.jd');
                jd_input.addEventListener('keyup', function() { //注意这里不能用keypress和keydown,因为这两个事件触发的时候,文字还没有落入文本框中,所以会出现按下第一个键的时候大号字体的盒子不被显示,之后大号字体盒子里的内容总比实际输入少一位。况且keypress还不识别删除键
    
                    if (this.value == '') {
                        con.style.display = 'none';
                    } else {
                        con.style.display = 'block';
                        con.innerHTML = this.value;
                    }
                })
                
                //当我们失去焦点,就隐藏这个con盒子
                jd_input.addEventListener('blur', function(){
                    con.style.display = 'none';
                })
                 //当我们获得焦点,就显示这个con盒子
                 jd_input.addEventListener('focus', function(){
                    if (this.value == '') {
                        con.style.display = 'none';
                    } else {
                        con.style.display = 'block';
                        con.innerHTML = this.value;
                    }
                })
            </script>
        </div>
    </body>
    
  • 相关阅读:
    2016年工作中遇到的问题11-20
    分布式服务框架Dubbo入门案例和项目源码
    分布式服务框架Dubbo入门案例和项目源码
    小米网抢购系统开发实践和我的个人观察
    小米网抢购系统开发实践和我的个人观察
    大学毕业4年-回顾和总结(8)-全局观-互联网项目研发-不在其位亦谋其政
    大学毕业4年-回顾和总结(8)-全局观-互联网项目研发-不在其位亦谋其政
    某电商项目的若干技术问题
    某电商项目的若干技术问题
    ZOJ 3861 Valid Pattern Lock
  • 原文地址:https://www.cnblogs.com/deer-cen/p/12241150.html
Copyright © 2011-2022 走看看