Event Event topics

Knowledge points:

## 知识点

- 事件监听器
  - 事件监听和事件绑定的区别 
  - addEventListener(type, listener[, options|useCapture])
    - 事件流
      - 事件冒泡
      - 事件捕获
    - 事件监听相关配置
      - capture   是否在捕获阶段执行
      - once   是否只执行一次
      - passive  阻止取消默认事件 
  - removeEventListener 取消事件监听   (不能用匿名函数)
- Event 事件对象
  - Event.target、Event.currentTarget 事件源
  - 事件委托(事件代理)
    - 事件委托的优点
      1. 可减少需要添加事件绑定的元素
      2. 可给新增DOM元素添加事件(在不刷新页面的情况下)
    - 事件委托的缺点
      1. 事件处理函数中需要判断事件源增加逻辑复杂度。
        2. 祖父级和事件源之间不能有阻止冒泡 
  - mousenter、mouseleave 事件  - 这俩个事件 不会在鼠标移动父子级切换过程中触发
  - Event.stopPropagation()、Event.cancelBubble 取消冒泡   
  - Event.clientX、Event.clientY、Event.pageX、Event.pageY 鼠标位置获取
- contextmenu 事件 
  - return false 和 Event.preventDefault() 阻止默认事件   

- 键盘事件
  - keydown、keyup
  - Event.keyCode、Event.key
  - Event.altKey、Event.ctrlKey、shiftKey
  - 制作组合键 
- 拖拽思路详解
  - mousedown、mousemove、mouseup
  - 拖拽公式:元素当前位置 = (鼠标当前位置 - 鼠标初始位置) + 元素初始位置
  - 拖拽问题修复
  - 限制范围拖拽
- 鼠标滚动事件
  - mousewheel 和 DOMMouseScroll 事件 
  - Event.wheelDelta 和  Event.detail 滚轮方向获取
- 其他常用事件:
  - dblclick
  - blur、focus、change、input、submit、reset
  - 表单其他方法:blur()、focus()、select()

1. Event Listeners

1.1 event listener and event bindings difference

  1. Event binding way, write multiple events, the following events will be covered by the above events; event listener mode (do not write on), multiple events can exist at the same time;
  2. Event binding manner not to cancel the event; event listener listening mode can be canceled, but must function must be anonymous function;

The results of the following: printed just 2:00 onclick event; when using event listeners addEventListener (), will be followed by printing 1,2

    <style>
        #box {
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
<div id="box"></div>
<script>
{
    let box = document.querySelector("#box");
    //事件绑定方式:通过事件绑定方式写多个事件,后面的事件会覆盖前面的事件
    // box.onclick = () =>{
    //     console.log(1);
    // }
    // box.onclick = () =>{
    //     console.log(2);
    // }

    //事件监听方式:事件不能写on,多个事件都会执行
    box.addEventListener('click',()=>{
        console.log(1);
    });
    box.addEventListener('click',()=>{
        console.log(2);
    });

}
</script>
</body>

1.2 addEventListener(type, listener[, options|useCapture])

1.2.1 event stream

  1. - event bubbling: Event execution order from the child to the parent. The default is the bubbling event execution
  2. - Event Capture: time to execute grade properties from the parent to the child. addEventListener (type, listener [, options | useCapture]) The third parameter is true is to capture the execution, if it is false just do not capture the execution, the default is false.
  3. Note: Event capture and bubbling to perform, whether child or parent events and specific events trigger location and the scope of the relevant sub-parent

Bubble Time: JS in properties, events bubble, when performing sub-element event, if the parent element has the same event, will be executed.

As shown below: If p, div, body, document has a click event when clicking p, p, div, body, document the event will be executed, and executed in the order of p div body document

    <style>
        #box {
            width: 400px;
            height: 400px;
            border: 1px solid black;
        }
        p {
            display: block;
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
<div id="box">
    <p></p>
</div>
<script>
{
    let box = document.querySelector("#box");
    let p = box.querySelector("p");

    box.addEventListener('click',()=>{
        console.log("div");//打印 div
    });
    //事件冒泡:在执行子元素的事件时,如果父元素也存在同样事件,父元素的事件也会执行
    p.addEventListener('click',()=>{
        console.log("p");//先打印 p 再打印div
    });

}
</script>
</body>

Event Capture:  Event execution order from parent to child

addEventListener (type, listener [, options | useCapture]) The third parameter is true is to capture the execution, if it is false just do not capture the execution, the default is false.

    <style>
        body {
            border: 1px solid green;
        }
        #box {
            width: 400px;
            height: 400px;
            border: 1px solid black;
        }
        p {
            display: block;
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
<div id="box">
    <p></p>
</div>
<script>
{
    let box = document.querySelector("#box");
    let p = box.querySelector("p");
    let body = document.querySelector("body");

    //事件捕获:通过addEventListener(type, listener[, options|useCapture])的第三个参数进行控制,如果是true就是捕获执行,是false就是不捕获执行,即事件默认为冒泡执行
    body.addEventListener('click',()=>{
        console.log("body");//只点击body时,只会打印body
    },true);

    box.addEventListener('click',()=>{
        console.log("div");//在div范围内p标签范围外,点击会打印body div
    },true);
    p.addEventListener('click',()=>{
        console.log("p");//会打印 body div p 
    },true);

}
</script>
</body>

Note: Event capture and bubbling to perform, whether child or parent events and specific events trigger location and the parent of the child about the range:

As shown below:

If the event is a bubbling, just click on the body, will print only body, click on the print div div body, click on the print p p, div, body;

If event capture, just click on the p, will print p, click on the div, prints div, p, click on the body print body, div, p

Because of the inconsistent range p div body

1.2.2 the order of execution of the event flow

Source: http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
event object with the DOM event flow turn down the final pass from the Window to the event target. But before this process begins, the transmission path of the event object needs to be determined.
The transmission path is an ordered list, which contains the node passed to the event to go through the target. The transmission path reflects the tree structure of the document. The last one is inside the target list of events, a list of which prior to its entry to the target node's ancestor, it's on to the target of a parent.
On the example of FIG Window-> Document-> html-> body-> table-> tr-> td. Once the transmission path is determined, the event object can be subjected to one or more events stages. There are typically three phases: the capture phase , the goal stage , bubbling phase . Some stages may be skipped if the browser does not support, or the propagation of an event object is stopped. For example, if cancelBubbleset true, bubbling phase will be skipped, or stopPropagation()method is invoked before passing it, after all of the stages will be skipped.

  • Capturing phase : The event object from an ancestor node goals Window began to spread until the target.
  • Target stage : the event object passed to the event target. If the event's type attribute indicates the back will not be bubbling operation, then this event is over.
  • Bubbling phase : the event object passed in the opposite direction, beginning from the target to the end of the Window object.

Link: https: //www.jianshu.com/p/dc1520327022

1.2.3 Event Listener other third parameter configuration

addEventListener (type, listener [, options | useCapture]) third argument can also pass objects

  1. - capture whether the capture phase, true table captures execution, false bubbling execution
  2. - once whether to perform only once. true setting is performed only once, false more than once. Even after setting to capture or bubbling execution, and only once
  3. - passive prevent cancel default event. true to prevent default event canceled, false does not prevent the default event canceled
    <style>
        body {
            border: 1px solid green;
        }
        #box {
            width: 400px;
            height: 400px;
            border: 1px solid black;
        }
        p {
            display: block;
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
<div id="box">
    <p></p>
</div>
<script>
{
    let box = document.querySelector("#box");
    let p = box.querySelector("p");
    let body = document.querySelector("body");

    //addEventListener(type, listener[, options|useCapture])第三个参数传递对象时,有三个值
    /*
        - capture  是否在捕获阶段执行,true时为捕获执行
        - once   是否只执行一次。
        - passive  阻止取消默认事件 
    */
    body.addEventListener('click',()=>{
        console.log("body");
    },{
        capture:true,
        once:true 
    });

    box.addEventListener('click',()=>{
        console.log("div");
    },{
        capture:true
    });
    p.addEventListener('click',()=>{
        console.log("p");
    },{
        capture:true//此处为捕获执行,但是body中设置了once:1,第一次点击p时会执行body div p;第二次以后就只会执行div p 
    });

}
</script>
</body>

 passive prevent cancel default event :

<body>
<a href="http://www.baidu.com">百度</a>
<script>
{
    let a = document.querySelector("a");
    a.addEventListener('click',(e)=>{
        e.preventDefault();//a标签默认有点击后跳转功能, e.preventDefault()可以取消其默认跳转
    },{
        passive:true //当设置passive:true后,e.preventDefault()取消默认事件就会被阻止,默认事件又可以执行
    });
}
</script>
</body>

1.3removeEventListener cancel the event listener (can not use an anonymous function)

If you need to cancel an event listener, you must use a named function when adding an event listener, to ensure the cancellation of the event listener function and the function to add to the same function object.

    <style>
        div {
            width: 200px;
            height: 200px;
            background: red;
        }
    </style>
</head>
<body>
    <div></div>
    <button>取消事件</button>
<script>
{
    let div = document.querySelector("div");
    let btn = document.querySelector("button");
    // div.addEventListener('click',()=>{
    //     console.log("div");
    // });
    // //发现这种方式取消不了div上的事件,因为div添加和取消监听里的函数虽然很像,但是不是同一个对象,所以取消不了
    // btn.addEventListener('click',()=>{
    //     div.removeEventListener('click',()=>{
    //         console.log("div");
    //     });
    // });

    //正确取消监听事件,必须添加和取消监听时都使用有名函数
    function fn(){
        console.log("div");
    }
    div.addEventListener('click',fn);
    //发现这种方式取消不了div上的事件,因为div添加和取消监听里的函数虽然很像,但是不是同一个对象,所以取消不了
    btn.addEventListener('click',()=>{
        div.removeEventListener('click',fn);
    });

}
</script>
</body>

 2.Event event object

Event function has a default argument, that event object, and is stored in event-related attributes.

2.1Event.target, Event.currentTarget event source

e.target: target element event triggered. That objective source.

e.currentTarget: element event binding.

    <style>
        div {
            width: 200px;
            height: 200px;
            background: red;
        }
        p {
            width: 100px;
            height: 100px;
            background: blue;
        }
    </style>
</head>
<body>
    <div>
        <p></p>
    </div>
<script>
{
    let div = document.querySelector("div");
    let p = document.querySelector("p");
    div.addEventListener('click',function(e){
        // console.log(e);//获取到的是事件对象
        console.log(e.target);//事件在哪个元素触发就是哪个
        console.log(e.currentTarget);//永远是事件绑定的元素
    });

}
</script>
</body>

2.2 event delegate (event agency)

- Advantages event delegate

  1. You can reduce the need to add elements bound events
  2. DOM elements can be added to the new event (without refreshing the page)

- shortcomings event delegate

  1. Event handler is necessary to determine the logical event source increases complexity.
  2. There is not between the grandparent and prevent bubbling event source (once to stop bubbling, the event delegate can not be used)

Requirements: change li ul style when clicked, but does not change the style of the label p

    <style>
        li {
            width: 100px;
            height: 100px;
            background: red;
            margin: 10px;
        }
        p {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
</head>
<body>
    <ul>
        <li>
            <p></p>
        </li>
        <li>
            <p></p>
        </li>
        <li>
            <p></p>
        </li>
        <li>
            <p></p>
        </li>
    </ul>
<script>
{
    //需求:在ul点击时改变li的样式,但是不改变p标签的样式
    let ul = document.querySelector("ul");
    ul.addEventListener('click',function(e){
        //通过事件委托,将li的事件点击委托给ul
        //真正的事件委托,需要判断目标元素是不是要添加事件的元素
        
        if(e.target.tagName == "LI"){
            e.target.style.background = "yellow";
        }
    });
}
</script>
</body>

2.3mousenter, mouseleave event

  1. mouseover and mouseout event if the mouse into or out of sub-elements, will trigger mouseover and mouseout events.
  2. mousenter, mouseleave not trigger mouse events in a parent-child class mobile switching process. That is not disturbed by the child elements
    <style>
        div {
            width: 100px;
            height: 100px;
            background: red;
        }
        p {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
</head>
<body>
    <div>
        <p></p>
    </div>
<script>
{
    //需求:给div加上鼠标移入移出事件
    let div = document.querySelector("div");
    let p = document.querySelector("p");
    div.addEventListener("mouseover",function(){
        console.log("鼠标移入了");
    });
    div.addEventListener("mouseout",function(){
        console.log("鼠标移出了");
    });
}
</script>
</body>

Result: The triggers div out of the event moved to the sub-elements, and then moved into the div trigger event. That is when the child moved into the div element div will trigger the mouse moved out of the event 

Use mouseenter and mouseleave:

    //需求:给div加上鼠标移入移出事件
    let div = document.querySelector("div");
    let p = document.querySelector("p");

    //使用mouseenter和mouseleave事件:不受子级元素影响
    div.addEventListener("mouseenter",function(){
        console.log("鼠标移入了");
    });
    div.addEventListener("mouseleave",function(){
        console.log("鼠标移出了");
    });

2.4Event.stopPropagation (), Event.cancelBubble cancel bubbling

  1. When the child element of the event itself, and do not want to execute the parent event elements, can be used to cancel event bubbling realized.
  2. Event.cancelBubble = true method, also supported in IE, then it supports advanced browser;
  3. Event.stopPropagation () is the standard method w3c cancellation bubbling;
    <style>
        div {
            width: 100px;
            height: 100px;
            background: red;
        }
        p {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
</head>
<body>
    <div>
        <p></p>
    </div>
<script>
{
    //需求:元素有自身的事件,不想执行父级的的事件
    let div = document.querySelector("div");
    let p = document.querySelector("p");
    div.addEventListener('click',function(e){
        console.log("div");
    });
    p.addEventListener('click',function(e){
        //在子级中取消冒泡事件,就不会执行父级中的事件了
        //最开始只有IE中能使用,现在高级浏览器版本也可以使用了
        // e.cancelBubble = true;

        //w3c中标准的取消冒泡事件方法
        e.stopPropagation();
        console.log("p");
    });

}
</script>
</body>

2.5 Event.clientX, Event.clientY, Event.pageX, Event.pageY get the mouse position

  1. Event.clientX, Event.clientY: Get the mouse position with respect to the visible region of the element, the element may be a document or body
  2. Event.pageX, Event.pageY: get the mouse position relative to the upper left corner of the page. Also with respect to the upper left corner of the page when the scroll bar
    <style>
        body {
            width: 600px;
            height: 600px;
            border: 1px solid red;
        }
        div {
            width: 100px;
            height: 100px;
            background: red;
        }
        p {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
</head>
<body style="height:3000px">
    <div>
        <p></p>
    </div>
<script>
{
    //需求:获取鼠标位置
    let div = document.querySelector("div");
    let p = document.querySelector("p");

    document.addEventListener('click',function(e){
        //获取鼠标相对于可视区的坐标位置
        console.log(e.clientX,e.clientY);//452 566

        //获取鼠标相对于页面左上角的坐标位置
        console.log(e.pageX,e.pageY);//452 1666
    });
     
}
</script>
</body>

Example: mouse to follow

The best use pageX and pageY, so that by the time of the scroll bar, there is no problem

 Use mousemove event when the mouse moves, div follow

    <style>
        div {
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>
<body>
    <div></div>
<script>
{
    //需求:鼠标跟随
    let div = document.querySelector("div");

    document.addEventListener('mousemove',function(e){
        //获取鼠标相对于页面左上角的坐标位置
        div.style.top = e.pageY + 'px';
        div.style.left = e.pageX + 'px';
    });
}
</script>
</body>

3.contextmenu mouse right click event

return false and Event.preventDefault () to prevent the default event

Note: return false; use only onXXX binding event; and e.preventDefault (); can also be used in binding events using event listeners, but you can not use the element e.target commissioned after the event

Right-click events are generally added to the document

Example: Customizing the context menu

    <style>
        body {
            margin: 0;
            padding: 0;
        }
        ul {
            display: none;
             position: absolute;
             top: 0;
             left: 0;
        }
         li {
             width: 200px;
             height: 30px;
             border: 1px solid black;
             list-style: none;
         }
    </style>
</head>
<body>
    <ul>
        <li>刷新</li>
        <li>跳转</li>
        <li>加载</li>
        <li>首页</li>
    </ul>
<script>
{
    //需求:自定义鼠标右击菜单
    let ul = document.querySelector("ul");

    document.addEventListener('contextmenu',function(e){
        //鼠标右击时首先取消默认鼠标右击事件
        e.preventDefault();

        //再让ul显示
        ul.style.display = "block";

        //鼠标右击时,让ul在右击的位置
        ul.style.top = e.pageY + 'px';
        ul.style.left = e.pageX + 'px';
        console.log(e.pageX,e.pageY);
        
    });
}
</script>
</body>

 

4. keyboard events

  1. - keydown、keyup
  2. - Event.keyCode、Event.key
  3. - Event.altKey、Event.ctrlKey、Event.shiftKey
  4. - Making key combination

Keyboard events and attributes:

  • keydown keyboard down event;
  • keyup keyboard up event;
  • e.keyCode key code;
  • e.key key
  • e.altKey: whether the alt key was depressed
  • e.ctrlKey whether pressing ctrl key
  • e.shiftKey whether the shift key is pressed
    //需求:键盘事件
    document.addEventListener('keydown',function(e){
        console.log("键盘按下");
        console.log(e.keyCode);
        console.log(e.key);
        console.log(e.ctrlKey);
        console.log(e.altKey);
        console.log(e.shiftKey);
        
    });
    document.addEventListener("keyup",function(e){
        console.log("键盘抬起");
    });

Use the key combination:

Demand: ctrl + up arrow enlarged div; ctrl + div narrow down arrow; up / down / left / right arrow, div moved in the corresponding direction

 

    <style>
        div {
            width: 200px;
            height: 200px;
            background: red;
            position: absolute;
            top: 50px;
            left: 100px;
        }
    </style>
</head>
<body>
    <div></div>
<script src="mTween.js"></script>
<script>
{
    //需求:按上下左右箭头时,div向对应方向移动;按ctrl+向上箭头,div放大,按ctrl+向下箭头,div缩小
    let div = document.querySelector("div");
    var scale=1;
    
    document.addEventListener('keydown',function(e){
        let top = css(div,"top");
        let left = css(div,"left");
    console.log(top,left);
        //上下左右的keyCode分别为:左 37;上38;右 39;下40; ctrl 17
        let code = e.keyCode;
        switch(code){
            case 37:
                css(div,"left",left-5);
                break;
            case 38:
                css(div,"top",top-5);
                break;
            case 39:
                css(div,"left",left+5);
                break;
            case 40:
                css(div,"top",top+5);
                break;
        }
        if(e.keyCode==38 && e.ctrlKey){
            scale+=0.5;
            div.style.transform='scale('+scale+')';
        }
        if(e.keyCode==40 && e.ctrlKey){
            scale-=0.5;
            div.style.transform='scale('+scale+')';
        }
    });
}
</script>
</body>

5. Detailed dragging ideas

- mousedown、mousemove、mouseup

- drag formula: = current position of the elements (the current mouse position - the initial position of the mouse) + Elemental initial position

- Drag bug fixes (mouseup perform multiple events)

- to limit the scope drag

Ideas:
            1, obtaining div element in an initial position (left, Top)
            2, obtaining the mouse initial position
            3 acquires the current mouse position
            4, the element current location = (current mouse position - mouse initial position) + Elemental initial position
            5, resolved beyond border issues

 Requirements: drag the mouse to another location div

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            top: 50px;
            left: 100px;
        }
    </style>
</head>
<body>
    <div></div>
<script>
{
    //需求:鼠标拖拽div到其他位置
    /*
        思路:
            1,获取元素div的初始位置(left,top)
            2,获取鼠标初始位置
            3,获取鼠标当前位置
            4,元素当前位置 = (鼠标当前位置-鼠标初始位置)+元素初始位置
            5,解决超出边界问题
    */
    let div = document.querySelector("div");
     //获取元素div的初始位置
     let divInitPos = {};

    //获取鼠标初始位置
    let initPos = {};
    div.addEventListener('mousedown',function(e){
        //获取元素初始位置必须在mousedown里,否则记录不到每次点击mousedown时元素的位置
        divInitPos.t = div.offsetTop;
        divInitPos.l = div.offsetLeft;

        initPos.x = e.clientX;
        initPos.y = e.clientY;
        
        //监听鼠标移动,鼠标移动事件设置在document上,才不会甩出去
        document.addEventListener('mousemove',drag);

        //鼠标放下时,停止移动,即清除鼠标移动事件
        //因为mouseup是在每次mousedown注册事件时就会进行注册,所以每点一次,以后就会进行累加,所以需要设置每次点击mousedown后,只执行一次mouseup
        div.addEventListener('mouseup',function(e){
            document.removeEventListener('mousemove',drag);
        },{
            once:true
        });
    });

    function drag(e){
            //获取移动时鼠标的当前位置
            let curPos = {};
            curPos.x = e.clientX;
            curPos.y = e.clientY;

            let divFinalPos = {};
            divFinalPos.t = (curPos.y-initPos.y)+divInitPos.t;
            divFinalPos.l = (curPos.x-initPos.x)+divInitPos.l;
            //解决:拖拽时超出边界问题
            //小于0时设置为0
            divFinalPos.t = Math.max(0,divFinalPos.t);
            divFinalPos.l = Math.max(0,divFinalPos.l);

            //超过宽高后,等于宽高。获取浏览器可视宽高
            let maxL = document.documentElement.clientWidth - div.offsetWidth;
            let maxT = document.documentElement.clientHeight - div.offsetHeight;
            divFinalPos.t = Math.min(maxT,divFinalPos.t);
            divFinalPos.l = Math.min(maxL,divFinalPos.l);

            //设置鼠标移动时,div位置跟着变化
            div.style.top = divFinalPos.t + "px";
            div.style.left = divFinalPos.l + "px";
        }
    
}
</script>
</body>
</html>

6. Scroll mouse events

  1. - mousewheel and DOMMouseScroll events. Two events at the same time there will be no written conflict
  2. - Event.wheelDelta direction acquisition rollers and Event.detail

mousewheel event is only compatible with Chrome and IE;

  • Up scroll wheel: Print 120
  • Stop rolling up roller: Print 240
  • Wheel Scroll down: printing -120
  • Stop scroll wheel up: printing -240

DOMMouseScroll event is only compatible with FireFox;

  • Scroll wheel up: Print -3
  • Stop scroll wheel up: print -6
  • Wheel Scroll down: -3 Print
  • Wheel stops scrolling down: 6 Print
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
<div></div>
<script>
{
    let div = document.querySelector("div");
    let width = div.offsetWidth;//width原始宽度
    //mousewheel事件只能在Chrome和IE中使用
    document.addEventListener('mousewheel',function(e){
        //e.wheelDelta
        width = e.wheelDelta>0? (width += 5):(width -= 5);
        div.style.width = width + 'px';

    });
    //只能在FireFox中使用
    document.addEventListener('DOMMouseScroll',function(e){
        //e.detail
        //e.detail<0时向上滚动
        width = e.detail<0? (width += 5):(width -= 5);
        div.style.width = width + 'px';
    });
}
</script>
</body>
</html>

Mouse wheel - Packaging Method:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
<div></div>
<script>
{
    let div = document.querySelector("div");
    let h = div.offsetHeight;//Height原始高度

    toWheel(div,function(){
        h+=5;
        //这里可以使用this,是因为封装函数时,将其this指向进行了更改
        this.style.height = h + 'px';
    },function(){
        h-=5;   
        this.style.height = h + 'px';
    });

    function toWheel(el,downFn,upFn){
        el.addEventListener('mousewheel',function(e){
            if(e.wheelDelta>0){
                //向上
                //如果直接调用this执行window,可以改变其this指向
                upFn&&upFn.call(this);
            }else{
                //向下
                downFn&&downFn.call(this);
            }
        });
        el.addEventListener('DOMMouseScroll',function(e){
            if(e.detail>0){
                //向上
                upFn&&upFn.call(this);
            }else{
                //向下
                downFn&&downFn.call(this);
            }
        });
    }
}
</script>
</body>
</html>

7. Other common events

- dblclick double click event

- blur、focus、change、input、submit、reset事件

  • Performing loses focus blur of the mouse cursor;
  • Executed when the mouse cursor focus gain focus;
  • change the contents of the implementation of the change. Loses focus, if the content is changed on the trigger; earlier than the execution blur
  • When modify the content execution input. Triggered when the content changes, the sensitivity is higher than Change;

- Form other methods: blur (), focus (), select ()

  • () Content select the selected text box
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<button>双击</button>
<form action="">
    <input type="text" id="txt">
    <br>
    <input type="submit" value="提交" id="sub">
    <input type="reset" value="重置" id="res">
</form>
<script>
{
    let btn = document.querySelector("button");
    let txt = document.querySelector("#txt");
    let sub = document.querySelector("#sub");
    let res = document.querySelector("#res");
    
    btn.addEventListener('dblclick',function(){
        alert("双击了");
    });
    //blur、focus、change、input、submit、reset事件
    txt.addEventListener('focus',function(){
        console.log("获取焦点");
    });
    txt.addEventListener('blur',function(){
        console.log("失去焦点");
    });
    txt.addEventListener('input',function(){
        console.log("内容修改时");
    });
    txt.addEventListener('change',function(){
        console.log("内容修改,且失去光标后");
    });

    //必须内容有改变才能提交
    sub.addEventListener('submit',function(e){
        e.preventDefault();
        console.log("提交");
        return false;
    });
    res.addEventListener('reset',function(){
        console.log("重置");
    });

    //blur()、focus()、select()
    //当按下空格键32时,获取光标;alt 18时失去光标;16 shift键选中文本
    document.addEventListener('keydown',function(e){
        console.log(e.keyCode);
        let code = e.keyCode;
        if(e.keyCode == 9){
            txt.blur();
        }
        if(e.keyCode == 32){
            txt.focus();
        }
        if(e.keyCode == 16){
            txt.select();
        }
    });
}
</script>
</body>
</html>

Difference and prevent the assignment of 8.select and selectstart

select: This event is triggered after selecting the input textarea or contents. Therefore, only the input and textarea tag support. Ctrl + A to select the mouse and can be monitored. But select events can not stop selected by default.

selectstart: Triggered when the left mouse button to select the start. For inhibiting selection page text: Further ff / opera does not support this event, ff can be controlled using css: css: body {-moz-user -select: none;}. webkit browsers can use "-khtml-user-select", of course, also be used to prevent users from onselectstart events within the selected text element. Note that this event does not support input and textarea invalid . For textarea or input tag, you can listen to Ctrl + A Select All function, but the left mouse button to select all invalid. When using the non selectstart input and textarea tag, does not listen to Ctrl + A. Listens to trigger the start when the left mouse button to select.

<input type="text" value="kaikeba">
<div>
    kaikebakaikebakaikebakaikebakaikebakaikebakaikebakaikebakaikebakaikebakaikebakaikeba
</div>
    let input = document.querySelector("input");
    //对input和textarea使用:可以监听到Ctrl+A的全选功能,但是鼠标左键全选无效
    input.addEventListener("selectstart",function(e){
        console.log("input");
        e.preventDefault();
    }); 

As result: Ctrl + A to select all time, it will be monitored, but the use of e.preventDefault (); it will not be selected. When you use the left mouse button to select, not selectstart listening to, so e.preventDefault () does not work, or can be selected.

    let div = document.querySelector("div");  
    div.addEventListener("selectstart",function(e){
        console.log("div");
        e.preventDefault();
    });

Above: When using the non selectstart input and textarea tag, does not listen to Ctrl + A. Listens to trigger the start when the left mouse button to select. Here e.preventDefault () will prevent selected by default

    input.addEventListener("select",function(e){
        console.log("select");
        e.preventDefault();
    }); 

Above: When using select, when the mouse to select the trigger will trigger after use ctrl + a check. But select events can not stop cancel selected by default. Therefore, use e.preventDefault (); there is no effect.

9. prevent assignment

To prevent the text is assigned, it is necessary to prevent ctrl + c, right assignment, and selected events selectstart default behavior.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box{
            width: 200px;
            height: 200px;
            background: red;
            position: absolute;
            top:200px;
            left: 200px;
        }
    </style>
</head>
<body>
    <div class="box">
        这是一段文字
    </div>

    <script>
        document.addEventListener('keydown',function(e){
            if(e.keyCode == 67 && e.ctrlKey){
                console.log('复制了')
                // 阻止浏览器默认行为?
                e.preventDefault();
            }
        })

        // 选中文字事件
        document.addEventListener('selectstart',function(e){
            console.log('选中')
            e.preventDefault()
        })

        // 阻止鼠标右键
        document.addEventListener('contextmenu',function(e){
            e.preventDefault();
        })
        
    </script>
</body>
</html>

10. Custom Event

Demand: Press: when the mouse is over 750 msec long press on a trigger element

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<a>长按</a>    
<script>

    // onclick  ...

// 长按: 当鼠标在一个元素上长按超过 750 毫秒触发
let longTap = new Event("longTap",{
    bubbles: true //如果设定为 false 也就是这个事件不冒泡,那就只能在那个元素上触发,那就只有这个一个元素是有这个事件的
});//自定义一个新事件

let timer = 0;

{

    let a = document.querySelector("a");
    a.addEventListener("mousedown",function(){
        clearTimeout(timer);
        timer = setTimeout(()=>{
            a.dispatchEvent(longTap); // 在 a 标签触发,a 及它所有的父级都会有这个事件
            // 如果是document触发,就只有 document 及 它的父级有这个事件,document 的内容就没有了
            
        },750);
    });
    a.addEventListener("mouseup",function(){
        clearTimeout(timer);
    });
    document.addEventListener("longTap",function(e){
        if(e.target == a){
            console.log("这是一个长按事件");
        } 
    });
}

</script>    
</body>
</html>

 

Published 95 original articles · won praise 115 · views 120 000 +

Guess you like

Origin blog.csdn.net/qq_34569497/article/details/99199337