Basic concept

  • When the browser reads the file content, it does not immediately parse and draw the interface. Instead, it first parses the label into an object and constructs a DOM tree, and then renders the tree according to the DOM tree + CSS to draw the interface. (The page is redrawn as soon as the element object in the DOM tree changes).
  • Dom objects are created from tags in HTML code, and each tag creates a Dom object, which together form a Dom tree.
  • WebAIP: BOM and DOM, a set of browser-provided apis that modify and manipulate objects in the DOM tree to control page interaction. (A series of methods that browsers give us to use)
  • Event three elements: event source, event type, and event handler

DOM

Access to elements

// Return null if no element is found
document.querySelector('.box');/ / class
document.querySelector('#nav');// id
document.querySelector('li');// The first li
document.querySelectorAll('li');/ / all li
document.querySelector('.box').querySelectorAll('li');

// Get the body tag
document.body;
// Get the HTML tag
document.documentElement;
Copy the code

Operating elements

Changing element content

// It can be modified or read
div.innerText='Returns the content inside the tag (does not contain HTML tags) does not recognize HTML tags';
div.innerHTML='Recognize HTML tags (recommended)';

<div><p>What's inside</p></div>

div.innerText; // The contents
div.innerHTML; 

Copy the code

Common property operations

// It can be modified or read
src/href
id/alt/title

img.src='/images/zxy.jpg';
Copy the code

Form property operations

// It can be modified or read
#input/textarea/select

type/value/checked/selected/disabled

<input type="checkbox" checked>
input.checked;// True if checked, false if unchecked
Copy the code

Style property operations

You can only get inline style sheets

// Can only be modified
#1.Div. Style Inline style manipulation// Take the hump nomenclature
- div.style.backgroundColor='blue';
- div.style.color='blue';
- div.style.display='none';

#2.Div. ClassName className style operation// Changes its class name directly, overwriting the original class name
- div.className='first change';
- div.className=' ';
Copy the code

Exclusive ideas

// Optimization of exclusivity
let lis = document.querySelectorAll('li');
for (let i = 0; i < lis.length; i++) {
	// All buttons. Onclick share a method!!
	lis[i].onclick = click;
}

// Exclusive function (public)
function click() {
	// Kill everyone
	for (let i = 0; i < lis.length; i++) {
		lis[i].style.backgroundColor = 'lightcoral';
	}
	Leave me alone
	this.style.backgroundColor = 'lightblue';
}
Copy the code

Classlist properties

The classList attribute is a new HTML5 attribute that returns the class name of an element. But IE10 and later support it.

Add the class:

Element.classlist.add (‘ class name ‘);

focus.classList.add('current');
Copy the code

Remove the class:

Element.classlist. remove (‘ class name ‘);

focus.classList.remove('current');
Copy the code

Switch:

Element.classlist. toggle (‘ class name ‘);

focus.classList.toggle('current');
Copy the code

Note: in the above method, all class names are not marked

Attribute operation

Dom element attributes

  1. Standard properties
    • Browsers create DOM objects based on HTML tags, and the attributes in the objects are standard attributes
    • For example, id, name, style, type….Note: To get the style. property, you can only get inline styles.
    • Operation mode: Directly through the object. Property name
      • Get the property value:dom.name
      • Set the property value:dom.checked=true
      • The standard properties of the DOM cannot be deletedDelete dom.name// Cannot be deleted
let o={a:'123'.b:'456'};
delete o.a;
console.log(o);//{b:'456'};
Copy the code
  1. Custom attributes

    • Because custom attributes are not added to the DOM object, but are placed in attributes within the DOM object, they cannot be used directly through the DOM. Custom property to get

    • Attributes that programmers add to the DOM through HTML tag syntax or DOM syntax

    • Such as < a href = “1. HTML” mydog = “Ricky” > < / a >

    • How it works: you must use dom.getarrtribute () and dom.setarrtribute ()

      • Get the property value:dom.getArrtribute('mydog'); // ricky
      • Set the property value:dom.setArrtribute('mydog','motty')
      • Add custom attribute values:dom.setAttribute('mycat','miao')
      • Delete a custom attribute:dom.removeAttribute('mydog');
  2. H5 Custom Attributes (data-)

    • Operation mode:
      • Get the property value:Dom. GetArrtribute (' property ')orThe dom. The dataset. Properties
      • Set/Add attributes:dom.setArrtribute('mydog','motty'); ordom.dataset.mycat='miao';
      • Delete a custom attribute:dom.removeAttribute('mydog');ordelete dom.dataset.mycat;

Note:

  • GetAttribute and setAttribute are versatile, and various attributes can be obtained or manipulated
  • Add your own custom attributes and try to start with data-

added

  1. Set custom properties by dot

    ① The attribute can be set successfully, but it is not set in the tag. It will not be displayed in the tag.

    (2) The dot call can get the attribute value, but the getAttribute method cannot

  2. Set attributes using the setAttribute method

    (1) You can set the attribute successfully and set it in the label

    ② You must use the getAttribute method to obtain the attribute value

Node operation

Everything node

  • The browser parses the HTML page and creates the contents of the page as node objects
  • Node objects have many types and all have the same three properties: nodeType, nodeName, and nodeValue
  • Common node types:
    • Element nodes: Generated from HTML tags
    • Text node: The text inside or outside the tag
    • Comment node

Gets the label name of the node

e.target.nodeName=='A';// Label names should be capitalized
e.target.tagName=='A'

ol.addEventListener('click'.function(e) {
            if (e.target.nodeName == 'A') {
                letli = e.target.parentNode; ol.removeChild(li); count--; todocount.innerHTML = count; }})Copy the code

parent-child

  1. The parent node

    • Dom. parentNode will find all nodes of the parent (including text nodes, etc.)

    • Dom.parentelement will only find the parentElement node

    • They differ only when the parent HTML tag is removed, but otherwise the parent element is removed and the effect is the same.

      // Document. documentElement is an HTML tag, and its parent element is document, not a tag
      - document.documentElement.parentNode;// #document 
      - document.documentElement.parentElement;// null
      Copy the code
  2. Child nodes

    • ul.childNodes, find all child nodes (element nodes text nodes, etc.)
    • ul.childrenIt is also us to get all child element nodesThe actual developmentThe commonly used
    • ol.children[0] / ol.children[ol.children.length - 1].The actual developmentIs written without compatibility problems and returns the first child
    • ol.firstChild / ol.lastChild, the first/last child node whether text node or element node
    • ol.firstElementChild / ol.lastElementChild, returns the first child element node supported only by IE9

Brother nodes

  1. The nextSibling contains element nodes or text nodes and so on

    • div.nextSibling
    • div.previousSibling
  2. NextElementSibling Gets the next sibling node, recommended (incompatible before IE9)

    • div.nextElementSibling
    • div.previousElementSibling
  3. Get all sibling nodes

    for(let li of lis){
      li.onclick= liClick;
    }
    
    function liClick(){
      let arrNext=[];
      let nextE=this.nextElementSibling;
      // When the next sibling of the element can still be found
      while(nextE){
        arrNext.push(nextE);
        nextE=nextE.nextElementSibling;
      }
      console.log(arrNext);
    }
    Copy the code

Create/Add/remove element nodes

A dynamically created/added element node. Note that the node cannot be obtained externally

// 1. Create node element node (existing in content)
var li = document.createElement('li');

Node. appendChild(child) Node's parent child is an append element similar to the push element in an array
ul.appendChild(li);

InsertBefore (create dom, specify element);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);

RemoveChild (child element);
ul.removeChild(ul.children[0]);
Copy the code

Copy the node

// Make a copy of the node. All properties of the node are copied.

1.Shallow copy ()/(false) copies only the current element itself, not the child node node.clonNode();2.Deep copy (true) copies the contents of the current element, including its children node.clonNode(true);
Copy the code

Get focusinput.focus()

// 1. Autofocus, the page is automatically focused when loaded
<textarea name="" id="" autofocus></textarea>
<button disabled>release</button>

// 2. Text.focus (), click button to make the textbox focus;
button.onclick=function(){
   text.focus();
}

// 3.
<label for="male">Male</label>
<input type="radio" name="sex" id="male" />
Copy the code

Message Posting Cases

<body>
    <textarea name="" id="" autofocus></textarea>
    <button disabled>release</button>
    <ul>

    </ul>
    <script>let text = document.querySelector('textarea'); let btn = document.querySelector('button'); let ul = document.querySelector('ul'); text.onkeyup = textKeyup; Function textKeyup() {if (! Function textKeyup() {if (! this.value.trim()) { btn.disabled = true; } else { btn.disabled = false; } } btn.onclick = btnClick; function btnClick() { let li = document.createElement('li'); li.innerHTML = text.value; // li.innerHTML = text.value + '<span>X</span>'; Let del = document.createElement('span'); del.innerHTML = 'X'; li.appendChild(del); AppendChild (li); // Add li ul.appendChild(li); // Clear the text box and focus on text.value = "; text.focus(); // Add a click event to the delete button # do not write to the outside, because the current dynamic delete button is not available outside!! Because you need to click BTN to dynamically create li del.onclick = delCLick; } function delCLick() {let isOk = confirm(' do you want to delete? '); RemoveChild (this.parentelement); // If (isOk) { } else {// If cancel, exit function return; }}</script>
</body>
Copy the code

Dynamically generate cell cases

<body>
    <table cellspacing="0">
        <thead>
            <tr>
                <th>The name</th>
                <th>subjects</th>
                <th>results</th>
                <th>operation</th>

            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>
    <script>
        // 1. Prepare students' data first
        var datas = [{
            name: 'Wei Yingluo'.subject: 'JavaScript'.score: 100
        }, {
            name: 'hong li'.subject: 'JavaScript'.score: 98
        }, {
            name: 'Fu Heng'.subject: 'JavaScript'.score: 99
        }, {
            name: 'MingYu'.subject: 'JavaScript'.score: 88
        }, {
            name: 'Big pig trotter'.subject: 'JavaScript'.score: 0
        }];
        let tbody = document.querySelector('tbody')

        // Iterate over the number group to generate data rows
        for (let stu of datas) {
            let tr = document.createElement('tr');
            tbody.appendChild(tr);
            // Iterate over the student object to generate cells
            for (let k in stu) {
                let td = document.createElement('td');
                td.innerHTML = stu[k];
                tr.appendChild(td);
            }
            // Generate delete cells
            let del = document.createElement('td');
            del.innerHTML = ' delete < / a > ';
            tr.appendChild(del);

            // Add click event to delete button
            del.onclick = delClick;
        }

        function delClick() {
            let isOk = confirm('Are you sure you want to delete it? ');
            if (isOk) {
                tbody.removeChild(this.parentNode);
            } else {
                return; }}</script>
</body>
Copy the code

Three dynamically created element differences

  1. Document.write () creates the element if the page document flow has been loaded, calling this statement will cause the page to be redrawn

    
            
    123
    var btn = document.querySelector('button'); btn.onclick = function() { document.write('<div>123</div>'); } Copy the code
  2. InnerHTML creates the element

    var inner = document.querySelector('.inner');
    
    // Method 1: string concatenation (slowest)
    // The reason for the slow:
    // 1. Each time the HTML code is parsed, the DOM object is generated, the DOM tree is added, and the page is redrawn (most time-consuming).
    // 2. Each loop resets the innerHTML of the body, causing the page to be redrawn 1000 times
    console.time();// Start the timer
    for (var i = 0; i <= 1000; i++) { 
    	inner.innerHTML += '
    }
    console.timeEnd();// End the timer
    
    
    
    // Array concatenation (fastest)
    // Fast reason: 4ms
    // Create 1000 DOM objects by setting the innerHTML of all generated tags at once
    // You only need to parse the code once and redraw the page once
    var arr = [];
    for (var i = 0; i <= 1000; i++) {
    	arr.push(');
    }
    inner.innerHTML = arr.join(' ');
    Copy the code
  3. Document.createelement () creates the element

    for (var i = 0; i <= 1000; i++) {
    	var a = document.createElement('a');
    	document.body.appendChild(a);
    }
    // Speed is in the middle
    // Slow cause: 17ms
    // 1. Create objects 1000 times
    // 2. Redraw the page 1000 times
    Copy the code
  4. document.createDocumentFragment()

    // Create code snippets (to temporarily store newly created DOM objects)
    var frag = document.createDocumentFragment();
    
    for (var i = 0; i <= 1000; i++) {
    	var a = document.createElement('a');
    	frag.appendChild(a);
    }
    // Add code snippets to body (add 1000 internal divs to body at once)
    document.body.appendChild(frag);
    
    // Slow cause: 7ms
    // 1. Create objects 1000 times
    // 2. Add 1000 objects to the page once and redraw the page once
    Copy the code

The event, a senior

An event is essentially a property of an object, and the added function is its property value.

Register events (2 ways)

  1. Traditional registration (starting with ON)

    • Uniqueness of registered events
    • Only one handler can be set for an element and an event. If there are more than one, subsequent registrations will override the previous one
    • Level 0 DOM events
    • Properties are added directly to dom objects
  2. Listener registration (addEventListener())

    • W3c standard recommendation (not supported before IE9, can use attachEvent()- not recommended instead)

    • Multiple listeners can be registered for the same element and event

    • By default, they are executed in the order of registration

    • Level 2 DOM events

    • Properties are not added to DOM objects, but to the in-memory dom event table at level 2 (virtual)

<script>
    var btns = document.querySelectorAll('button');
    // 1. Register events the traditional way
		// hao a u
    btns[0].onclick = function() {
        alert('hi');
    }
    btns[0].onclick = function() {
            alert('hao a u');
    }
   // 2. Register event addEventListener
   // The event type inside (1) is the string must be quoted without on
   // (2) Add more listeners to the same element and event
   //  22 33
    btns[1].addEventListener('click'.function() {
        alert(22);
    })
    btns[1].addEventListener('click'.function() {
            alert(33);
    })
</script>
Copy the code

Delete event (unbind event)

  1. Traditional Registration

    • eventTarget.onclick=null;
  2. Method listens for the registration mode

    • eventTarget.removeEventListener(type, listener[, useCapture ]);
    • eventTarget.detachEvent( eventNameWithOn , callback ); (Not recommended)
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
            alert(11);
            // 1. Delete events in the traditional way
            divs[0].onclick = null;
        }
        // 2. RemoveEventListener Deletes the event
        divs[1].addEventListener('click', fn) // Fn inside does not need to be called with parentheses
        function fn() {
            alert(22);
            divs[1].removeEventListener('click', fn);
        }

        // 3. detachEvent
        divs[2].attachEvent('onclick', fn1);

        function fn1() {
            alert(33);
            divs[2].detachEvent('onclick', fn1);
        }
    </script>
Copy the code

The DOM event flow

The event stream is the order in which events are received from the page

When events occur, they are propagated in a specific order before element nodes, which is called the DOM event stream

The DOM event flow goes through three stages:

  1. Capture phase

  2. Current target stage

  3. Bubbling phase

If we throw a stone into the water, it will first have a descent process, which can be understood as the capture process from the topmost layer to the most specific element of the event (the target point); Bubbles are then created and float to the surface of the water after the lowest point (the most specific element), a process equivalent to event bubbling.

Note:

  • Js can only capture or bubble one of the phases.

  • Onclick and attachEvent only get the bubbling phase

  • The third parameter to add is useCapture

    • True, the capture phase
    • False (do not write default values), bubble phase
  • Pay more attention to events bubbling up

  • Some events are not bubbling, such as onblur, unfocus, onMouseEnter, onmouseleave

The event bubbling

// Click son to execute son's click event first... And finally document

		<div class="father">
        <div class="son">Son box</div>
    </div>
    <script>
        // Onclick and attachEvent (ie) fire in the bubbling phase
        If the third addEventListener parameter is false or omitted
        // son -> father ->body -> html -> document
        var son = document.querySelector('.son');
		// Register the son click event
        son.addEventListener('click'.function() {
            alert('son');
        }, false);
		// Register the father click event
        var father = document.querySelector('.father');
        father.addEventListener('click'.function() {
            alert('father');
        }, false);
		// Register the document click event, omitting the third argument
        document.addEventListener('click'.function() {
            alert('document');
        })
    </script>
Copy the code

Event capture

// Click son to execute document first... And finally son

		<div class="father">
        <div class="son">Son box</div>
    </div>
    <script>
        // If the third addEventListener() argument is true then it is emitted during the capture phase
        // document -> html -> body -> father -> son
         var son = document.querySelector('.son');
		// Register the son click event with the third parameter true
         son.addEventListener('click'.function() {
             alert('son');
         }, true);
         var father = document.querySelector('.father');
		// Register the click event for father with the third parameter true
         father.addEventListener('click'.function() {
             alert('father');
         }, true);
		// Register the document click event with the third parameter true
        document.addEventListener('click'.function() {
            alert('document');
        }, true)
    </script>
Copy the code

The event object

After an event occurs, the collection of information data related to the event is put into this object, which is the event object.

Who bound the event, mouse position, which key was pressed, etc

Event objects are generated when an event firing occurs and are passed by the system as arguments to the event handler.

Event object compatibility handling

In IE6~8, the browser does not pass parameters to methods. If necessary, you need to go to window.event to look for them.

    <div>123</div>
    <script>
        var div = document.querySelector('div');
        div.onclick = function(e) {
                // Event object
                e = e || window.event;
                console.log(e);
        }
    </script>
Copy the code

Properties and methods of the event object

The difference between e.target and this

  • This is the element of the event binding (the element that binds the event handler).

  • E.target is the element that triggers the event.

Usually terget and this are the same, but when the event bubbles (the parent element has the same event, and clicking on the child element triggers the parent element’s event handler), this refers to the parent element because it is the element object to which the event is bound. Target refers to the child element because it is the specific element object that triggered the event.

# event bubbling under e.target andthis

    <ul>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
				// Click the li tag, the event will bubble to ul
        ul.addEventListener('click'.function(e) {
              // we bind the event to ul so this points to ul
              console.log(this); // ul

              // e.target is the object that triggered the event. We clicked on Li
              console.log(e.target); // li
        });
Copy the code

Blocking default behavior

Some tags in the HTML have default behaviors. For example, after a tag is clicked, the page is redirected by default.

# e.preventDefault();    

		<a href="http://www.baidu.com">baidu</a>
    <script>
      
        // 2. Prevent the default behavior from skipping links
        var a = document.querySelector('a');
        a.addEventListener('click'.function(e) {
             e.preventDefault(); // dom standard
        });

        // 3. Traditional registration method
        a.onclick = function(e) {
            // common browser e.preventdefault (); Method ## recommend ##
            e.preventDefault();
          
            // Lower version Browser IE678 returnValue property
            e.returnValue = false;
          
            // We can also use return false to prevent the default behavior from being incompatible
            // Note that the code after return does not execute and is limited to traditional registration
            return false;
        }
    </script>
Copy the code
// When the form is clicked submit, the form's data is submitted by default.
// Can be added to the form to block the submit event, or to the submit button## It is recommended to submit events through the form, since forms can have multiple submit buttons and all submit the form, so it should be uniformly blocked in form submission eventslet fNode=document.querySelector('form');
fNode.addEventListener('submit'.function(e){
  e.preventDefault();
});
Copy the code
// Prevents the default event from selecting text at the beginning of the page
document.addEventListener('selectstart'.function(e){
      e.preventDefault();
})
Copy the code

Prevents events from bubbling

  • The standard of writing

    e.stopPropagation(); // stop Stops Propagation
    Copy the code
  • Non-standard notation IE678

    window.event.cancelBubble = true; // Nonstandard Cancel Cancels bubble
    Copy the code
    <div class="father">
        <div class="son">Son son</div>
    </div>
    <script>
        var son = document.querySelector('.son');
		// Register the son click event
        son.addEventListener('click'.function(e) {
            alert('son');
            e.stopPropagation(); // stop Stops Propagation
            window.event.cancelBubble = true; // Nonstandard Cancel Cancels bubble
        }, false);

        var father = document.querySelector('.father');
		// Register the father click event
        father.addEventListener('click'.function() {
            alert('father');
        }, false);
		// Register the document click event
        document.addEventListener('click'.function() {
            alert('document');
        })
    </script>
Copy the code

Event delegation

Event delegates are also called event proxies, or event delegates in jQuery.

In plain English, you do not register events for child elements, register events for parent elements, and execute the processing code in the event of the parent element.

The principle of event delegation

  • Register events for the parent element and use event bubbling. When the child element’s event is triggered, it will bubble to the parent element and then control the corresponding child element.

  • That is, delegating the child element's events to the parent element via bubbling

  • Delegate to an existing element

The role of event delegation

  • We only manipulated the DOM once, improving the performance of the program.
  • Dynamically newly created child elements also have events.
  • Application: By registering click events for UL, click events can be added to newly created Li in the future through event delegation
< button > new < / button ><ul>
    <li>You know what? I should have a frame in hand!</li>
    <li>You know what? I should have a frame in hand!</li>
    <li>You know what? I should have a frame in hand!</li>
    <li>You know what? I should have a frame in hand!</li>
    <li>You know what? I should have a frame in hand!</li>
</ul>
<script>
	let btnAdd = document..querySelector('button');
	var ul = document.querySelector('ul');

	// Dynamically add li
	btnAdd.addEventListener('click'.function(e) {
		let newLi = document.createElement('li');
    newLi.innerHTML = '我是新加的li'+Math.radom();
    ul.appendChild(li);
})	
	
			
	// The core principle of event delegation is to add listeners to the parent node and use event bubbling to affect each child node
	// You can add click events to future li's
	ul.addEventListener('click'.function(e) {
		// e.target this will get the object we clicked on
    e.target.style.backgroundColor = 'pink';
})
</script>
Copy the code

Common Mouse events

Example: Disable text selection and right-click menus

// Disable is usually to prevent the browser from displaying the default right-click menu, because you need to write the style function of the right-click menu, etc<body> I'm a text I don't want to share <script>// contextMenu we can disable the right menu
        document.addEventListener('contextmenu'.function(e) {
                e.preventDefault();
        })
        // 2. Disable selectStart
        document.addEventListener('selectstart'.function(e) {
            e.preventDefault();
        })
    </script>
</body>
Copy the code

mouseout

Note: Mouseout is triggered only when the mouse removes the edge of the target element, not when it “steps” over other elements

Pay attention to the point

  1. Mouseover and mouseout can fire in both parent and child elements, depending on the number of children when the mouse passes over an element.
  2. Mouseenter and mouseleave fire only on the parent element, and only once when the mouse moves over an element;
  3. When all four functions are used in parent elements, mouseover and mouseout fire before mouseEnter and mouseleave;
  • In general:
    • Mouseover is used with mouseout and mouseEnter is used with mouseleave
    • Use mouseover and mouseout if there are no children inside the element.
    • If the element has child elements, use mouseEnter and mouseleave to prevent events from bubbling.

Mouse event object

Get the coordinates of the mouse on the page (pageX)

// the MouseEvent object MouseEvent
document.addEventListener('click'.function(e) {
    // 1. The client mouse is in view of the x and Y coordinates
    console.log(e.clientX);
    console.log(e.clientY);
    console.log('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -');

    // 2. Page mouse over page document x and Y coordinates!! Focus!!!!!
    console.log(e.pageX);
    console.log(e.pageY);
    console.log('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -');

    // 3. The mouse is in the x and Y coordinates of the computer screen
    console.log(e.screenX);
    console.log(e.screenY);

})

Copy the code

Case study: An angel with a mouse

<img src="images/angel.gif" alt="">
    <script>
        var pic = document.querySelector('img');
        document.addEventListener('mousemove'.function(e) {
        	// 1. Mousemove will trigger this event whenever the mouse moves 1px
        	// 2. Core principle: Every time the mouse moves, we will get the latest mouse coordinates,
            // Use the x and y coordinates as the top and left values to move the image
          // Note that top left is the coordinate relative to the document
        	var x = e.pageX;
        	var y = e.pageY;
        	console.log(The x-coordinate is zero. + x, 'The y-coordinate is'. + y);
        	//3. Don't forget to add px units to left and top
        	pic.style.left = x - 50 + 'px';
        	pic.style.top = y - 40 + 'px';
    	});
    </script>
Copy the code

Common keyboard events

Keyboard events

Execution order of three events: keyDown — keypress — keyup

Difference between keyUp and KeyDown

Text box content input and keyDown and keyUp order

  1. The keyDown event is emitted before the text box has entered the content of the pressed button

  2. Adds a key to a text box

  3. When the key is lifted, the KeyUp event is triggered

    In a text box, the keyUp event is usually used

Keyboard event object

KeyCode — returns the ASCII value of the value e.keycode===65 // determines whether to press the A key

Note:

  • Onkeydown and onKeyUp are case insensitive, onKeyPress is
  • In practice, onKeyDown and onKeyUp are used more often

Case: simulated jingdong key input content

// Add the event to keyDown
// 1. Trigger the document's keyDown event, which determines that if the s key is pressed, the text box gets focus
// 2. The text box gets focus
// 3. The browser will then type the pressed S key into the element currently in focus

// Add the event to keyUP
Trigger a keyDown event for the document, but in this case no keyDown event is added to the document, so nothing happens
// 2. The browser then presses the s key into the current focus element, but there is no focus element on the page, so nothing happens
// 3. Trigger the keyUp event of the document so that the text box gets focus

		<input type="text">
    <script>
        // Get the input box
        var search = document.querySelector('input');
		// Register the keyUp event for document
        document.addEventListener('keyup'.function(e) {
            // Determine the value of keyCode
            if (e.keyCode === 83) {
                // Triggers a focus event for the input box
                search.focus();
              	search.
            }
        })
    </script>
Copy the code

Case: Simulate jingdong express tracking number query

Check whether the text box is empty: this.value.trim().length === 0

// Requirement: When we enter content in the text box, the text box automatically displays the content in large size.
<div class="search">
    <div class="con">123</div>
    <input type="text" placeholder="Please enter your tracking number" class="jd">
</div>

<script>
    // Get the element to operate on
    var con = document.querySelector('.con');
    var jd_input = document.querySelector('.jd');

    // Register the keyUp event for the input field
    jd_input.addEventListener('keyup'.function() // Check whether the input box is emptyif (this.value.trim().length === 0) {
    		// If empty, hide the zoom prompt box
      	con.style.display = 'none';
    	} else {
       	// Not empty, display the enlargement prompt box, set the box content
       	con.style.display = 'block';
       	con.innerText = this.value; }})// Register the out-of-focus event for the input box, and hide the zoom prompt box
    jd_input.addEventListener('blur'.function() {
    	con.style.display = 'none';
     })

     // Register the input field to get focus events
     jd_input.addEventListener('focus'.function() {
     	// Check whether the input box is empty
     	if (this.value ! = =' ') {
     		// display the prompt box if it is not empty
     		con.style.display = 'block'; }})</script>
Copy the code

BOM

Summary of BOM

The Browser Object Model (BOM) is the Browser Object Model. It provides objects that interact with the Browser window independently of content. The core Object is window. Operating the browser

A BOM is made up of a series of related objects, each of which provides a number of methods and attributes.

BOM lacks standards. The standardization body for JavaScript syntax is ECMA, the standardization body for DOM is W3C, and BOM was originally part of the Netscape browser standard.

The BOM is larger than the DOM, and it contains the DOM.

Top-level object Window

  • Is an interface for JS to access the browser

  • Is a global object. Variables and functions defined in the global scope become properties and methods of the Window object

    • The window can be omitted when called. Alert () and prompt() are window object methods
  • The next special property of window is window.name, so do not declare name in the global scope

Common events for window objects

Page (window) loading event (2 kinds)

Keep JS from having to be written at the bottom of an HTML file

1. The first one

  • Window. onload is a window (page) load event,When the document content is fully loadedTriggers the event (This includes images, scripts, and CSS files) to call the handler function.
  • Cons: If the connection is slow, the user sees the button first, but it doesn’t work when clicked
// Traditional registration can only be written once ## normal code uses ##
window.onload = function(){}

// There is no limit
window.addEventListener("load".function(){})
Copy the code

2. The second

  • The DOMContentLoaded event is triggered only when the DOM is loaded, excluding stylesheets, images, Flash, etc.

  • IE9 support only above!!

  • Only level 2 registration can be used

  • If there are many pictures on the page, it may take a long time from user access to onload trigger, and the interactive effect will not be realized, which will inevitably affect the user experience. In this case, DOMContentLoaded event is appropriate.

document.addEventListener('DOMContentLoaded'.function(){})
Copy the code

Resize window events

window.addEventListener('resize'.function(){}) 
Copy the code

Window. onresize is a handler that adjusts the window size to load the event and is called when triggered.

Note:

  1. This event is triggered whenever the window size changes by pixels.

  2. We often use this event for reactive layout. Window. innerWidth Width of the current screen

    <script>
        // Register page loading event
        window.addEventListener('load'.function() {
            var div = document.querySelector('div');
        	// Register the resize window event
            window.addEventListener('resize'.function() {
                // window.innerWidth Gets the window size
                console.log('Changed');
                if (window.innerWidth <= 800) {
                    div.style.display = 'none';
                } else {
                    div.style.display = 'block';
                }
            })
        })
    </script>
    <div></div>
Copy the code

The timer

Bomb timer

SetTimeout () Bomb start timer

window.setTimeout(call function, [number of milliseconds delayed]);// setTimeout This calling function is called callback
// Window can be omitted
// The number of milliseconds omitted defaults to 0

// Calling a function can write the function directly, or write the function name, or 'function name ()' is not recommended
    <script>
        The callback function is an anonymous function
         setTimeout(function() {
             console.log('Time is up');

         }, 2000);
        function callback() {
            console.log('Exploded');
        }
		Since there can be many timers, we often assign an identifier ## to timers
		// The callback function is a named function
        var timer1 = setTimeout(callback, 3000);// Return a single id
        var timer2 = setTimeout(callback, 5000);
    </script>
Copy the code

Stop timer

window.clearTimeout(timeoutID);// timeoutID is the timer identifier
Copy the code

Move the div box case

    <style>
        * {
            padding: 0;
            margin: 0;
        }
        
        div {
            position: absolute;
            width: 100px;
            height: 100px;
            background-color: lightcoral;
        }
    </style>    

		<script>
        window.onload = function() {
            let div = document.querySelector('div');
            let start = document.querySelector('.start');
            let stop = document.querySelector('.stop');
            let timeId = null;
            start.addEventListener('click'.function() {
                if (timeId) return;
                timeId = setInterval(function() {
                    let windowW = window.innerWidth - 100;
                    let xNum = parseInt(div.style.left);
                    console.log(xNum);
                    if (xNum >= windowW) {
                        clearInterval(timeId);
                        // timeId = null;
                        // return;
                    }
                    div.style.left = xNum + 10 + 'px';

                }, 20);
                stop.onclick = function() {
                    clearInterval(timeId);
                    timeId = null; }})}</script>
    <button class="start">mobile</button>
    <button class="stop">stop</button>
    <div style="left: 100px"></div>
Copy the code

Alarm clock timer

SetInterval () Indicates that the alarm starts the timer

// Call the callback function at intervals
window.setInterval(call function, [number of milliseconds between calls]);Copy the code

Stop timer

window.clearInterval(intervalID);// timeoutID is the timer identifier
Copy the code

Countdown case

        // 1. Get the element
        var hour = document.querySelector('.hour'); // Hour black box
        var minute = document.querySelector('.minute'); // Minute black box
        var second = document.querySelector('.second'); // The number of seconds of the black box
        var inputTime = +new Date('the 2019-10-25 18:00:00'); // Returns the total number of milliseconds the user entered
				// call it once so that the page has content as soon as it loads
        countDown();
        // 2. Start the timer
        setInterval(countDown, 1000);
        function countDown() {
            var nowTime = +new Date(a);// Returns the total number of milliseconds in the current time
            var times = (inputTime - nowTime) / 1000; // times is the total number of seconds left
            var h = parseInt(times / 60 / 60 % 24); / /
            h = h < 10 ? '0' + h : h;
            hour.innerHTML = h; // Give the remaining hours to the hour black box
            var m = parseInt(times / 60 % 60); / / points
            m = m < 10 ? '0' + m : m;
            minute.innerHTML = m;
            var s = parseInt(times % 60); // The current second
            s = s < 10 ? '0' + s : s;
            second.innerHTML = s;
        }
Copy the code

This points to the problem

  1. In a global scope or normal function, this refers to the global object Window.

  2. Whoever calls this points to in a method call

  3. Constructor this refers to an instance of the constructor

// 1. In the global scope or normal function, this refers to the global object Window.
function a(){
  console.log(this);//window
}
a();// window.a();

window.setTimeout(function() {
	console.log(this);// window
}, 1000); }// 2. Who calls this in the method call refers to who
var o = {
	sayHi: function() {
		console.log(this); // This refers to the object o
	}
}
o.sayHi();

// 3. Constructor this refers to an instance of the constructor
function Fun() {
	console.log(this); // This points to the fun instance
}
var fun = new Fun();
Copy the code

Location object

The location concept

URL

Location The property of the object

Key points: href and search

Href case

    // The page is automatically displayed after 5 secondsClick < button > < / button ><div></div>
    <script>
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        btn.addEventListener('click'.function() {
            // console.log(location.href);
            location.href = 'http://www.itcast.cn';
        })
        var timer = 5;
        setInterval(function() {
            if (timer == 0) {
                location.href = 'http://www.itcast.cn';
            } else {
                div.innerHTML = 'You will be in' + timer + 'Jump to home page in seconds'; timer--; }},1000);
    </script>
Copy the code

The search case

# login.html

<form action="index.html">User name:<input type="text" name="uname">Password:<input type="password" name="password" id="">
  <input type="submit" value="Login">
</form>

# index.html
<div></div>
<script>
	let div = document.querySelector('div');
	let data = UrlToObj(location.search);
  // decodeURIComponent(data.uname) decodes Chinese
  div.innerHTML = `The ${decodeURIComponent(data.uname)}Welcome, your password is:${data.password}`;

	// Convert location.search to an object
	function UrlToObj(urlParams) {
		let strParams = urlParams.substr(1); // uname=jean&password=1234
    let obj = {};
    let arrParams = strParams.split('&') // ["uname=jean","password=1234"]
    for (let p of arrParams) {
    	let key = p.split('='); // ['uname','jean']
      obj[key[0]] = key[1]; // { uname: 'jean'}
    }
    return obj;
	}
</script>
Copy the code

Common methods for location objects

Click < button > < / button ><script>
        var btn = document.querySelector('button');
        btn.addEventListener('click'.function() {
            // Record the browsing history, so you can implement the backward function
            // location.assign('http://www.itcast.cn');
            // The browser history is not recorded, so you cannot implement the backward function
            // location.replace('http://www.itcast.cn');
            location.reload(true);
        })
    </script>
Copy the code

The navigator object

The Navigator object contains information about the browser and has a number of properties, the most common being the userAgent, which returns the value of the User-Agent header of the server sent by the client.

The following front-end code can determine which terminal users open the page, to achieve the jump

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS |Symbian|Windows Phone)/i))) {
    window.location.href = "";     / / cell phone
 } else {
    window.location.href = "";     / / computer
 }
Copy the code

The history object

The Window object gives us a History object that interacts with the browser history. This object contains the URL that the user has visited (in the browser window).

The history object is rarely used in real development, but is found in some OA office systems.

The local store

Only strings can be stored; you can encode the object json.stringify () for storage

window.sessionStorage

1. The lifecycle is to close the browser window

2. Data can be shared in the same window (page)

3. Store and use in the form of key-value pairs

Storing data:

sessionStorage.setItem(key, value)
Copy the code

Get data:

sessionStorage.getItem(key)
Copy the code

Delete data:

sessionStorage.removeItem(key)
Copy the code

Clear data :(all cleared)

sessionStorage.clear()
Copy the code

window.localStorage

1, declare that the cycle is permanent, unless manually deleted or closed page will exist

2. Multiple Windows (pages) can be shared (the same browser can be shared)

3. Store them as key-value pairs

Storing data:

localStorage.setItem(key, value)
Copy the code

Get data:

localStorage.getItem(key)
Copy the code

Delete data:

localStorage.removeItem(key)
Copy the code

Clear data :(all cleared)

localStorage.clear()
Copy the code

JS execution mechanism

JS is single threaded

Single threading means that all tasks need to be queued until the first one is finished before the next one can be executed. If the first task takes a long time, the second task has to wait forever. The problem with this is that if the JS execution takes too long, the rendering of the page will be incoherent, causing the page rendering load to feel blocked.Copy the code

Synchronous and asynchronous tasks

All tasks in JS can be categorized into two types, synchronous and asynchronous. A synchronization task refers to a task that is queued to be executed on the main thread. The next task can be executed only after the first task is completed. Asynchronous tasks refer to tasks that do not enter the main thread but enter the "task queue". When the tasks in the main thread are finished, the asynchronous tasks are removed from the "task queue" and put into the main thread for execution.Copy the code

Callback function: the function is passed in as an argument

Event loop

Link and script tags

<! -- Link tag loads files asynchronously -->
<! When the browser encounters an external file with the link tag, it will make a separate request and continue executing the code itself.
<! -- Purpose: first display the page structure to the user, and then add style, beautify the interface -->
<link rel="stylesheet" href="01.css">
  
<! -- the script tag loads files synchronously -->
<! When the browser encounters an external file with a script tag, it will wait until the external JS file is loaded and continue to execute the following code.
<! * * * * * * * * * * * * * * * * * * * * *
<script src="01.js"></script>
<! Onload =function(){} -->
Copy the code

PC side web effects

Element offset series

Summary of offset

  1. Gets the element distance with the location of the parent element
    • Directly gets the result of the last style position operation (composite style sheet = inline style + inline style + outer chain style)
  2. Get the size (width and height) of the element itself
  3. Note: The values returned do not have units

<div class="father">
    <div class="son"></div>
</div>
<div class="w"></div>
<script>
    / / offset series
    var father = document.querySelector('.father');
    var son = document.querySelector('.son');
    // 1. We can get the ununitless value returned by the offset position of the element
    console.log(father.offsetTop);
    console.log(father.offsetLeft);
    // It takes the parent with the location. If there is no parent or the father has no location, the body will take the place
    console.log(son.offsetLeft);
    var w = document.querySelector('.w');
    // 2. You can get the size, width and height of the element, including padding + border + width
    console.log(w.offsetWidth);
    console.log(w.offsetHeight);
    // 3. Return the parent with the location otherwise return the body
    console.log(son.offsetParent); // Return the parent with the location otherwise return the body
    console.log(son.parentNode); // Return father is the closest level of father to father regardless of father location
Copy the code

Offset is different from style

offset

  • Offset can get the style value in any stylesheet

  • The values obtained by the offset series are ununitless

  • OffsetWidth contain padding + border + width

  • Properties such as offsetWidth are read-only and can only be obtained but cannot be assigned

  • So, we want to get the size of the element, offset is more appropriate

style

  • Style can only get style values from inline style sheets

  • Style.width returns a string with units

  • Style.width gets a value that does not contain the padding and border

  • Style. width is a read-write property that can be obtained or assigned

  • So, if we want to change the value of an element, we need to use a style change

Because we normally register touch events for elements, keep targetTocuhes in mind

Modal box drag and drop

 // 1. Get the element
        var login = document.querySelector('.login');
        var mask = document.querySelector('.login-bg');
        var link = document.querySelector('#link');
        var closeBtn = document.querySelector('#closeBtn');
        var title = document.querySelector('#title');
				// Prevents the default event from selecting text at the beginning of the page
				document.addEventListener('selectstart'.function(e){
          		e.preventDefault();
        })
        // 2. Click the pop-up link to make mask and login appear
        link.addEventListener('click'.function() {
                mask.style.display = 'block';
                login.style.display = 'block';
            })
            Click closeBtn to hide mask and login
        closeBtn.addEventListener('click'.function() {
                mask.style.display = 'none';
                login.style.display = 'none';
            })
            // 4. Start dragging
            // (1) When we mouse down, we get the coordinates of the mouse inside the box
        title.addEventListener('mousedown'.function(e) {
            var x = e.pageX - login.offsetLeft;
            var y = e.pageY - login.offsetTop;
            // (2) When the mouse moves, subtract the mouse's position in the page from the position in the box to create the left and top values of the modal box
          	// ### Since the mouse movement event can only be triggered when the mouse is pressed down, the main mouse can be moved in any position, so the event source is document
            document.addEventListener('mousemove', move)

            function move(e) {
                login.style.left = e.pageX - x + 'px';
                login.style.top = e.pageY - y + 'px';
            }
            // (3) Remove the mouse movement event
            document.addEventListener('mouseup'.function() {
                document.removeEventListener('mousemove', move); })})Copy the code

Magnifier effect

  window.onload = function() {
      / / the preview
      let preview_img = document.querySelector('.preview_img');
      / / mask layer
      let mask = document.querySelector('.mask');
      // Big box
      let big = document.querySelector('.big');
      / / a larger version
      let bigImg = document.querySelector('.bigImg');

      // Mouse over, mask and large image display
      preview_img.addEventListener('mouseover'.function(e) {
          mask.style.display = 'block';
          big.style.display = 'block';

      })

      // Mouse over, mask and large image hide
      / /!!!!! Mouseout must be triggered when the mouse moves the edge of the target element, not when it "steps" over other elements
      preview_img.addEventListener('mouseout'.function(e) {
          mask.style.display = 'none';
          big.style.display = 'none';
      })

      // Mouse movement
      preview_img.addEventListener('mousemove'.function(e) {
          // Coordinates of the mouse inside the box
          let x = e.pageX - this.offsetLeft;
          let y = e.pageY - this.offsetTop;
          // Coordinates of the mask layer = the coordinates of the mouse inside the box - half the size of the mask layer
          let maskX = x - mask.offsetWidth / 2;
          let maskY = y - mask.offsetHeight / 2;

          // The maximum distance the mask layer can move inside the box = the width of the box - the width of the mask layer
          let maskMax = this.offsetWidth - mask.offsetWidth;
          // Limit the distance the mask can move
          if (maskX < 0) {
              maskX = 0;
          } else if (maskX > maskMax) {
              maskX = maskMax;
          }
          if (maskY < 0) {
              maskY = 0;
          } else if (maskY > maskMax) {
              maskY = maskMax;
          }
          // The moving distance of the occlusion layer
          mask.style.left = maskX + 'px';
          mask.style.top = maskY + 'px';


          // 3. Moving distance of large picture = moving distance of occlusion layer * maximum moving distance of large picture/Maximum moving distance of occlusion layer
          // The maximum moving distance of a large image
          bigMax = bigImg.offsetWidth - big.offsetWidth;
          let bigX = maskX * bigMax / maskMax;
          let bigY = maskY * bigMax / maskMax;
          // The distance of the large image is X and Y
          bigImg.style.left = -bigX + 'px';
          bigImg.style.top = -bigY + 'px'; })}Copy the code

Element viewable client family

Taobao flexible. Js source code analysis

// flexible.js

(function flexible(window.document) {
    // Get the root element of the HTML
    var docEl = document.documentElement
        // DPR physical pixel ratio
    var dpr = window.devicePixelRatio || 1

    // Adjust Body font size Sets the font size for our body
    function setBodyFontSize() {
        // If the page has the body element set the body font size
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            // If the page does not have the body element, wait until the main DOM element of the page is loaded before setting the body element
            // The font size
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10 Sets the text size of our HTML element
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset REM unit on page resize When the page size changes, we need to reset the REM size
    window.addEventListener('resize', setRemUnit)
        // PagesHow is the event triggered when we reload the page
    window.addEventListener('pageshow'.function(e) {
        // e.persisted returns true, which means that if the page is cached, the rem size should also be recalculated
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports Some mobile browsers do not support 0.5 pixels
    if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
            docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
}(window.document))
Copy the code

Execute function immediately

Main effect: Creates a separate scope. Naming conflicts are avoided

Problem solved: When importing multiple files, the same variable or function name is used in different files, resulting in variable contamination

Solution: Use self-executing functions to generate separate scopes in each j file to avoid variable contamination

(function(){}) () or (function(){} ())Copy the code

pageshow

The load event is triggered in each of the following three cases where the page is refreshed.

1. Hyperlink of a label

2.F5 or refresh button (forced refresh)

3. Forward and back buttons

But firefox features a “round-trip cache” that not only stores page data, but also the DOM and JavaScript state; In effect, the entire page is stored in memory.

So the back button cannot refresh the page at this point.

This can be triggered using the PagesHow event. This event is triggered when the page is displayed, whether the page is from the cache or not. In the reload page, pagesHow fires after the load event fires; The pagesHow event that is emitted from the page in the cache will be checked from the persisted event object in the event object. Notice that this event is added to the window.

Element scroll series

Scroll Outlines

Scroll translates to scroll, and we can use the related properties of scroll series to dynamically obtain the size and scrolling distance of the element.

The head of the page that is rolled out

Scroll bars appear automatically if the browser is not tall (or wide) enough to display the entire page. When the scroll bar scrolls down, the height of the page is hidden, we call the page rolled out of the head. The onScroll event is triggered when the scroll bar scrolls.

Fixed right sidebar (window.pageyoffset)

  1. The original sidebar was absolutely positioned
  2. When the page scrolls to a certain location, the sidebar changes to a fixed location
  3. If the page continues to scroll, the return to the top will appear

Note:

  • The rolled out header for an element is element.scrollTop, or for a pagewindow.pageYOffset.
    • PageYOffset can be obtained from window.pageYOffset on the left if it is window.pageXOffset
    • If the value is greater than or equal to this value, the box can be fixed (note:OffsetTop is relative to body(the top of the entire page), the smaller the page scrolls.)
    • Fixed positioning is relative to the window (browser viewable area)In terms of,Absolute positioningIs relative to the location of the parent box, if there is no parent box, relative tobody(Top of the entire page)
        let sliderbar = document.querySelector('.slider-bar');
        let goBack = document.querySelector('.goBack');
        let banner = document.querySelector('.banner');
        let main = document.querySelector('.main');

        // banner. OffestTop is the size of the page with the head rolled off. This value does not change as the page scrolls
        let bannerTop = banner.offsetTop;
        // The top value when the sidebar is absolutely positioned at the beginning
        let sliderbarTop = sliderbar.offsetTop;
        // The value that should change when our sidebar is fixed
        let sliderbarTop1 = sliderbarTop - bannerTop;
        // Record the initial top value of main
        let mainTop = main.offsetTop;
        document.addEventListener('scroll'.function() {
          	// The sidebar should be fixed when the page is rolled to a head greater than or equal to bannerTop
            if (window.pageYOffset >= bannerTop) {
                sliderbar.style.position = 'fixed';
                // Remember to add px units
                sliderbar.style.top = sliderbarTop1 + 'px';
            } else {
                sliderbar.style.position = 'absolute';
                sliderbar.style.top = sliderbarTop + 'px';
            }

            // When we scroll to the main box, the goback module is displayed
            if (window.pageYOffset >= mainTop) {
                goBack.style.display = 'block';
            } else {
                goBack.style.display = 'none'; }})Copy the code

Series summary – to be added

Their main uses:

1. The offset family is often used to get the element position offsetLeft offsetTop

2. Client is often used to get the element size clientWidth clientHeight

3. Scroll is often used to obtain the scrolling distance scrollTop scrollLeft

4. Note that the scrolling distance of the page is obtained from window.pagexoffset

5. Mouse series

window

window.pageYOffset

// Page scroll event
document.addEventListener('scroll'.function() {
			// When we scroll to the main box, the goback module is displayed
			if (window.pageYOffset >= mainTop) {
					goBack.style.display = 'block';
			} else {
					goBack.style.display = 'none'; }})Copy the code

window.scroll()

window.scroll(x-coord, y-coord)
window.scroll(options)

// The x-coord value represents the x-coordinate of the pixel you want to place in the upper left corner.
// The y-coord value indicates the ordinate of the pixel you want to place in the upper left corner.

/ / sample<! -- Put the vertical axis on the100Three pixels at the top of the window --><button onclick="window.scroll(0, 100);">Click to scroll down 100 pixels</button>

/ / using the options:
window.scroll({
  top: 100.left: 100.behavior: 'smooth'
});
Copy the code

The difference between mouseEnter and mouseover

  • Mouseover is triggered when the mouse moves over its own box or over a child box. The mouseEnter is only triggered by its own box
    • Mouseover —– is triggered whenever the mouse is over the box (even if there are sub-boxes on the box)
    • Mousenter —— Entering its own box (containing the boundaries of the child box) triggers, at which point the child box and its parent can be seen as one
  • And the reason for that is becauseMouseenter does not bubble
  • Mouseleave also does not bubble when the mouse leaves the mouseEnter
  • When all four functions are used in parent elements, mouseover and mouseout fire before mouseEnter and mouseleave;

Animation function

How animation works

Core principle: Continuously move the box position through timer setInterval().

Implementation steps:

  1. Gets the current position of the box
  2. Add one movement distance to the current position of the box
  3. Repeat this with a timer
  4. Add an end timer condition
  5. Note that this element needs to be positioned to use element.style.left

Animation function encapsulation

If more than one element uses the animation function, var declares the timer each time. We can use different timers for different elements (we use our own timer exclusively).

Core principle: using JS is a dynamic language, can be very convenient to add attributes to the current object.

 function animate(dom, target) {
            // As we click the button over and over again, the element gets faster and faster because there are too many timers on
            // The solution is to have our element execute with only one timer
            // Clear the previous timer and keep the current one running
            clearInterval(dom.timerId);
            dom.timerId = setInterval(function() {
                if (dom.offsetLeft >= target) {
                    // Stop animation is essentially stop timer
                  	// Return is added to stop the current timer from executing down
                    return clearInterval(dom.timerId);
                }
                dom.style.left = dom.offsetLeft + 1 + 'px';

            }, 20);
}

// Call the function
animate(div, 300);
// Click btn1 to start the span animation
btn1.addEventListener('click'.function() {
     animate(span, 200);
})
// Click btn2 to stop the span animation
btn2.addEventListener('click'.function() {
     clearInterval(span.timerId)
})
Copy the code

Principle of slow motion effect

A slow animation is an element that moves at a different speed, most commonly to a slow halt

Ideas:

  1. Let the box move a smaller distance each time, the speed will slow down.
  2. Core algorithm:(Target value - current position) / 10As the distance step of each move
  3. The stop condition is: make the current box position equal to the target position to stop the timer
  4. Note that the step size needs to be rounded
function animate(dom, target) {
            // Clear the previous timer and keep the current one running
            clearInterval(dom.timerId);
  
            dom.timerId = setInterval(function() {
              	// Since the last few steps move 1px, you must reach the target position
                if (dom.offsetLeft == target) {
                    // Stop animation is essentially stop timer
                  	// Return is added to stop the current timer from executing down
                    return clearInterval(dom.timerId);
                }
              	// Write the step value to the inside of the timer =(target value - current position) / 10
                var step = (target - dom.offsetLeft) / 10;
                // If step>0, it is moving to the right. Round up (0.2=>1); Otherwise, it moves to the right and needs to be rounded down (-1.2 => -2)
              	step= step > 0 ? Math.ceil(step) : Math.floor(step);
              	// Change the integral by 1 to a progressively smaller value
                dom.style.left = dom.offsetLeft + step + 'px';

            }, 20);
}
Copy the code

Animation function moves between multiple target values

You can move the animation function from 800 to 500.

When we click the button, determine whether the step size is positive or negative

1. If the value is positive, the step size is rounded to a larger value

2. If the value is a negative value, the step size is rounded from a smaller value

var step = (target - dom.offsetLeft) / 10;
// If step>0, it is moving to the right. Round up (0.2=>1); Otherwise, it moves to the right and needs to be rounded down (-1.2 => -2)
step= step > 0 ? Math.ceil(step) : Math.floor(step);
Copy the code

The action function adds the callback function

How callback functions work: A function can be taken as an argument. Passing this function as an argument to another function, and then executing the function when that function is finished, is called a callback.

Where the callback function is written: where the timer ends.

callback && callback instanceof Function && callback();

function animate(dom, target, callback){
		if (dom.offsetLeft == target) {
				Callback is called if callback exists and is a function
        callback instanceof Function && callback();
				// Stop animation is essentially stop timer
				// Return is added to stop the current timer from executing down
				return clearInterval(dom.timerId); }}Copy the code

Web page rotation map

Also known as the focus graph, it is a common webpage effect in web pages.

Functional requirements:

1. When the mouse passes over the multicast diagram module, the left and right buttons are displayed, and the left and right buttons are hidden when the mouse leaves.

2. Click the button on the right once to play the picture to the left, and so on.

3. While the picture is playing, the following small circle module changes along with it.

4. Click the small circle to play the corresponding picture.

5. If the mouse does not move over the image, the image automatically plays.

  • Auto play function: equivalent to manually call click button event on the rightarrow_r.click();

6. When the mouse passes, the rotation graph module stops automatically.

    let timerF = false;
    focus.addEventListener('mouseenter'.function() {
        // Suspends the auto-playing of the carousel graph
        timerF = true;
    });

    focus.addEventListener('mouseleave'.function() {
        // The rotation chart continues to play automatically
        timerF = false;
    });    

		setInterval(function() {
        // If true, pause playback
        if (timerF) return;
        // Manually invoke the right click event
        arrow_r.click();
		}, 2000)
Copy the code

The complete code

window.addEventListener('load'.function() {
    / / the left arrow
    let arrow_l = document.querySelector('.arrow-l');
    / / right arrow
    let arrow_r = document.querySelector('.arrow-r');
    // Round the box
    let focus = this.document.querySelector('.focus');
    let focusWidth = focus.offsetWidth;
    // Determine whether to pause auto play
    let timerF = false;
    // 1. The arrow is displayed when the mouse cursor moves over the wheel cast graph
    focus.addEventListener('mouseenter'.function() {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        // Suspends the auto-playing of the carousel graph
        timerF = true;
    });

    // 2. Hide the arrow when the mouse cursor moves out of the cast image
    focus.addEventListener('mouseleave'.function() {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        // The rotation chart continues to play automatically
        timerF = false;
    });

    // Get the father ol of the bottom dot
    let ol = this.document.querySelector('.circle');
    // Get the parent ul of the focus graph
    let ul = focus.querySelector('ul');
    // 3. Dynamically generate small dots. If there are several images, generate several small dots
    for (let i = 0; i < ul.children.length; i++) {
        let li = document.createElement('li');
        // Record the current dot index number
        li.setAttribute('index', i);
        ol.appendChild(li);
    }

    // 4. Bind the dot's click event to the father'S OL through event delegate
    ol.addEventListener('click'.function(e) {
        // Remember to check whether the current clicked node is li (possibly a text node)
        if (e.target.nodeName == 'LI') {
            // Set the current class name exclusively
            for (let li of this.children) {
                li.className = ' ';
            }
            e.target.className = 'current';
            // Get the current li index
            let index = e.target.getAttribute('index');
            // When we click on a small li, we need to give the index number of the li to num and circle
            num = index;
            circle = index;
            // 5. Click the small circle and move the image to ul
            // the index of the small circle multiplied by the width of the image is negativeanimate(ul, -index * focusWidth); }});// Add current class name to the first dot by default
    ol.children[0].className = 'current';

    // 6. Clone the first image (li) and put it at the end of ul
    let first = ul.children[0].cloneNode(true);
    ul.appendChild(first);

    // 7. Click the button on the right to scroll a picture
    // Record the index of the image
    let num = 0;
    // Record the index of the small circle
    let circle = 0;
    / / throttle valve
    let flag = true;
    arrow_r.addEventListener('click'.function() {
        // 10. Only when one picture animation is finished, open the throttle and proceed to the next animation
        if (flag) {
            // Close the throttle valve
            flag = false;
            // If we get to the last image, our ul will quickly undo the left to 0
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * focusWidth, function() {
                // Open the throttle valve
                flag = true;
            });
            // 8. Click the button on the right to change the small circle. You can declare another variable to control the playing of the small circle
            circle++;
            // If circle == 4, we have reached the end of the cloned image
            if (circle == ol.children.length) {
                circle = 0;
            }
            circleChange();
        }
    })

    arrow_l.addEventListener('click'.function() {
        // 10. Only when one picture animation is finished, open the throttle and proceed to the next animation
        if (flag) {
            // Close the throttle valve
            flag = false;
            // If we get to the first image, our ul should quickly reach the last image
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * focusWidth + 'px';
            }
            num--;
            animate(ul, -num * focusWidth, function() {
                // Open the throttle valve
                flag = true;
            });
            // 8. Click the button on the right to change the small circle. You can declare another variable to control the playing of the small circle
            circle--;
            // If circle <0, you have reached the first image and need to jump to the last small circle
            if (circle < 0) {
                circle = ol.children.length - 1; } circleChange(); }})// As the image changes, the small circle changes
    function circleChange() {
        for (let li of ol.children) {
            li.className = ' ';
        }
        ol.children[circle].className = 'current';
    }

    // 10
    setInterval(function() {
        // If true, pause playback
        if (timerF) return;
        // Manually invoke the right click event
        arrow_r.click();
    }, 2000)})Copy the code

Throttle valve

To prevent fast playback caused by continuous clicking of the rotation chart button.

Choke valve purpose: When the previous function animation content is finished, to execute the next function animation, so that the event can not fire consecutively.

Core implementation idea: use callback function, add a variable to control, lock function and unlock function.

Start setting a variable var flag= true;

If(flag){flag = false; Do something} Turn off the tap

Using the callback function animation after execution, flag = true turn on the tap

arrow_l.addEventListener('click'.function() {
        // Only when a picture animation is complete, open the throttle and proceed to the next animation
        if (flag) {
            // Close the throttle valve
            flag = false;
            .
            .
            animate(ul, -num * focusWidth, function() {
                // Open the throttle valve
                flag = true; }); ..}})Copy the code

A touch screen event

A touch screen event

Touch event object

Because we normally register touch events for elements, keep targetTocuhes in mind

The mobile side drags elements

  1. Touchstart, TouchMove, and TouchEnd can implement dragging elements
  2. But the drag element requires the current finger coordinate value. We can use pageX and pageY inside targetTouches[0]
  3. The principle of moving terminal drag: finger movement, calculate the distance of finger movement. Then take the original position of the box + the distance your finger moves
  4. Distance of finger movement: the position of the finger in the slide minus the position of the finger at the beginning of the touch

Drag elements in three steps:

(1) Touch element touchStart: to obtain the initial coordinates of the finger and the original position of the box

(2) Touchmove finger: calculate the sliding distance of finger and move the box

(3) Leave the finger touchend:

Note: finger movement also triggers scrolling so prevent default scrolling here. E.preventdefault ();

Click delay solution

The mobile click event has a 300ms delay because the mobile screen double tap to zoom the page.

Solution:

1. Disable zooming. The browser disables the default double click zoom behavior and removes the 300ms click delay.

  <meta name="viewport" content="user-scalable=no">
Copy the code

2. Use the Touch event to encapsulate the event itself to resolve the 300ms delay.

The principle is:

  1. When we touch the screen with our finger, we record the current touch time
  2. When our finger leaves the screen, subtract the touch time from the time it leaves
  3. If the time is less than 150ms and the screen has not been swiped, we define it as a click

The code is as follows:

// Encapsulate tap to solve click 300ms delay
function tap (obj, callback) {
        var isMove = false;
        var startTime = 0; // Record the time variable when touching
        obj.addEventListener('touchstart'.function (e) {
            startTime = Date.now(); // Record the touch time
        });
        obj.addEventListener('touchmove'.function (e) {
            isMove = true;  // See if there is a slide. If there is a slide, it is drag, not click
        });
        obj.addEventListener('touchend'.function (e) {
            if(! isMove && (Date.now() - startTime) < 150) {  // Click if the finger touch and leave time is less than 150ms
                callback && callback(); // Execute the callback function
            }
            isMove = false;  // take the reverse reset
            startTime = 0;
        });
}
/ / call
  tap(div, function(){   // execute code});

Copy the code
  1. Use plug-ins. The FastClick plug-in solves the 300ms delay.

Making website

if ('addEventListener' in document) {
            document.addEventListener('DOMContentLoaded'.function() {
                       FastClick.attach(document.body);
            }, false);
}
Copy the code