Because the original DOM API was too long to remember, I wrapped a DOM library in object style -> source code link here to summarize the new wrapped API. Again, with add, remove, change and check to divide, we first provided a global window.dom object

increase

Create a node

create (string){
        const container = document.createElement("template")// Template can hold any element
        container.innerHTML = string.trim();// Remove whitespace from both sides of the string
        return container.content.firstChild;// With template, the elements inside must be retrieved like this
    }
Copy the code

First, if we use the original DOM API, we want to create a div that contains the text ‘hi’, which is a two-step process

  1. document.createElement('div')
  2. div.innerText = 'hi'

Dom.create (‘

hi

‘) can create multiple tag nesting directly, such as create(‘

hello

‘). Because we’re writing the string directly into the HTML with innerHTML, the string becomes the content of the HTML. Why use template? Because template can hold any element, if div is used, div cannot directly hold the < TD >
tag, but template can

New brother

before(node,node2){
    node.parentNode.insertBefore(node2,node);
    }
Copy the code

Find the parent node and use insertBefore to add node2

New brother

after(node,node2){
    node.parentNode.insertBefore(node2,node.nextSibling); // Insert node2 in front of the next node in a node, even if the next node is empty
    }
Copy the code

Since the original DOM only had insertBefore and no insertAfter, we need a curvilinear method to achieve this function: Node. nextSibling = nextSibling node.nextSibling = nextSibling node.nextSibling = nextSibling node2 = nextSibling node2

New son,

 append(parent,node){
        parent.appendChild(node)
    }
Copy the code

Find the parent node using appendChild

The new father

 wrap(node,parent){
        dom.before(node,parent)
        dom.append(parent,node)
    }
Copy the code

The idea is as follows:

Divided into two steps:

  1. Put the new parent node in front of the old node
  2. Put the old node into the new parent node

This allows the new parent node to wrap around the old node

Example:

const newDiv = dom.create('<div id="newParent"></div>')
dom.wrap(test, newDiv)
Copy the code

delete

Abridged point

remove(node){
       node.parentNode.removeChild(node)
       return node
    }
Copy the code

Find the dad node and remove vechild

Delete all child nodes

empty(node){
    const array = []
    let x = node.firstChild
    while (x) {
        array.push(dom.remove(node.firstChild))
        x = node.firstChild//x points to the next node
    }
    return array
    }
Copy the code

Actually, the idea from the beginning was to use a for loop

for(let i = 0; i<childNodes.length; i++){ dom.remove(childNodes[i]) }Copy the code

There is a problem with this approach: childNodes.length changes with deletion, so we need to change our approach and use a while loop:

  1. Find the first child of the node and assign it x
  2. When x exists, we remove it and place it in an array (to get a reference to the deleted node).
  3. Assign x to its next node (when the first son is deleted, the next son becomes the first son)
  4. Repeat this operation until all child nodes are deleted

change

Read and write attribute

 attr(node,name,value){
        if(arguments.length === 3){
            node.setAttribute(name,value)
        }else if(arguments.length === 2) {return node.getAttribute(name)
        }
    }
Copy the code

Overloading is used here to achieve two different functions:

  1. When three parameters are entered, attributes are written
  2. Read property when the number of arguments is 2

Example:

/ / write:
// Add attributes to 
      
test
dom.attr(test,'title'.'Hi,I am Wang')
test
/ / read: const title = dom.attr(test,'title') console.log(`title:${title}`) // Print out: title:Hi,Hi,I am Wang Copy the code

Reading and writing text content

text(node,string){
    if(arguments.length === 2) {if('innerText' in node){
            node.innerText = string
        }else{
            node.textContent = string
        }
    }else if(arguments.length === 1) {if('innerText' in node){
            return node.innerText
        }else{
            return node.textContent
        }
    }
}
Copy the code

Why do we need to match innerText and textContent here? Although most browsers now support both, there are older Versions of Internet Explorer that only support innerText, so this is for all browsers

Same idea as read/write properties:

  1. When two parameters are entered, text is written to the node
  2. If the input parameter is 1, read the text

Read and write HTML content

html(node,string){
    if(arguments.length === 2){
        node.innerHTML = string
    }else if(arguments.length === 1) {return node.innerHTML
        }
Copy the code

Similarly, parameter 2 writes content and parameter 1 reads content

Modify the Style

style(node,name,value){
        if(arguments.length === 3) {//dom.style(div,'color','red')
            node.style[name] = value
        }else if(arguments.length === 2) {if(typeof name === 'string') {//dom.style(div,'color')
            return node.style[name]    
            }else if(name instanceof Object) {//dom.style(div,{color:'red'})
                const Object = name
                for(let key in Object) {//key:border/color
                    //node.style.border = ...
                    //node.style.color = ...
                    node.style[key] = Object[key]
                } 
            }
        }
    }
Copy the code

Ideas:

  1. Firstly, judge the input parameters. If there are 3 parameters, for example:dom.style(div,'color','red')
  2. Change its style
  3. If two parameters are entered, check the type of the value of name
  4. If it is a string, for exampledom.style(div,'color'), returns the style property
  5. If it is an object, such asdom.style(div,{border:'1px solid red',color:'blue'}), change its style

Add or delete check class

class:{
    add(node,className){
        node.classList.add(className)    
    },
    remove(node,className){
        node.classList.remove(className)
    },
    has(node,className){
        return node.classList.contains(className)
    }
}
Copy the code

Note: This class contains an element in the classList

Adding Event Listeners

on(node,eventName,fn){
       node.addEventListener(eventName,fn) 
    }
Copy the code

Example:

const fn = () = >{
    console.log('Clicked')
}
dom.on(test,'click',fn)
Copy the code

So when you click on the div with the id test, it will print ‘Clicked’

Delete event listener

off(node,eventName,fn){
    node.removeEventListener(eventName,fn)
    }
Copy the code

check

Gets one or more labels

find(selector,scope){
    return (scope || document).querySelectorAll(selector)
    }
Copy the code

You can find it in the specified area or in the global document

Example: Query in document:

const testDiv = dom.find('#test') [0]
console.log(testDiv)
Copy the code

Query within a specified range:

 <div>
        <div id="test"><span>test1</span>
        <p class="red">Paragraph tags</p>
        </div>
        <div id="test2">
            <p class="red">Paragraph tags</p>
            </div>
    </div>
Copy the code

I only want to find red in test2, what should I do

const test2 = dom.find('#test2') [0]
 console.log(dom.find('.red',test2)[0])
Copy the code

Note: don’t forget to write the [0] at the end

Get the parent element

parent(node){
    return node.parentNode
    }
Copy the code

Get child elements

children(node){
    return node.children 
}
Copy the code

Gets the sibling element

siblings(node){
    return Array.from(node.parentNode.children).filter(n= >n! ==node)// Arraylist filters itself
    }
Copy the code

Find the dad node and filter out yourself

To get my brother

next(node){
    let x = node.nextSibling
    while(x && x.nodeType === 3){
        x = x.nextSibling
    }
    return x
    }
Copy the code

Why do WE need while(x && x.nodeType === 3)? Because we don’t want to get text nodes (Spaces, carriage returns, etc.), when we read a text node, we automatically read the next node until we read something other than a text node

Access to the elder brother

previous(node){
        let x = node.previousSibling
        while(x && x.nodeType === 3){
            x = x.previousSibling
        }
        return x
    }
Copy the code

Same idea as above

Iterate over all nodes

each(nodeList,fn){
        for(let i=0; i<nodeList.length; i++){ fn.call(null,nodeList[i])
        }
    }
Copy the code

Note: NULL is used to fill the position of this. Example use fn to change the style of all nodes

const t = dom.find('#travel') [0]
dom.each(dom.children(t),(n) = >dom.style(n,'color'.'red'))
Copy the code

Iterate through each node, changing the style of each node

Used to get the ranking number

index(node){
    const list = dom.children(node.parentNode)
    let i;
    for(i=0; i<list.length; i++){if(list[i]===node){
             break}}return i
    }
Copy the code

Ideas:

  1. Gets all the sons of the father node
  2. Set a variable I
  3. If I equals the node you want to query
  4. Exit the loop, returning the value of I