Nowadays, all kinds of frameworks and tools “run amok”, everywhere in the principle and source code, more cross-end technology needs us to explore, but if the basic skills are not good, learn what is half the effort, the effect is very bad, take time at the same time to blow confidence. This article, the first (11) in the series of “light talk front end” planned by me, aims to share the native JavaScript knowledge to you systematically and logically, helping you to easily understand and memorize the knowledge system, and I will do my best to live up to expectations.

In the first article in the series, we talked about what “programming” is, and Web programming naturally requires both elements – “programming” and “Web”.

We’ve already talked about several elements of programming.

  • “Variables”, for storing data;
  • Object, which encapsulates data;
  • “Array”, used to store a series of similar data;
  • “Function”, used to encapsulate behavior.

As a program, that’s all it takes, but many people have a problem moving from learning JavaScript to writing web pages — “Once you know the syntax, where do you start?” .

In order for code to actually act on and interact with web pages, you need two other things: DOM and BOM.

JavaScript = ES + DOM + BOM.

BOM — Browser Object Model, DOM — Document Object Model.

BOM is used to host web pages and DOM is used to display web pages.

The star of this article is DOM.

What is the DOM

In terms of presentation, it determines the content of the page; In terms of encoding, it contains attributes and capabilities.

The former is easy to understand, the latter is also familiar, is not the object? So DOM is a combination of a web page structure and a programming interface.

It is important to note that, despite the JavaScript formulas mentioned above, the DOM is not specific to JavaScript, but is cross-platform and language-neutral. This is related to JavaScript because JavaScript provides the DOM API.

Any HTML or XML document can be represented in the DOM as a hierarchy of nodes. There are many types of nodes, each of which corresponds to different information or tags in the document, has its own different features, data, and methods, and has relationships with other types that form a hierarchy that allows tags to be represented as a tree structure rooted in a particular node. This is what we call a DOM tree.

DOM is powerful, but for a long time it was a pain in the neck, cumbersome to use, versioned, incompatible, performance costly… The impression is that DOM is primitive and bad, and best avoided.

As a result, there is a lot of talk about how to “reduce” dealing with native DOM, such as Jquery/Zepto a few years ago, Vue and React a few years ago. The former has a good compatibility and encapsulation of DOM operations, and is more convenient to use, while the latter introduces “virtual DOM” and a more reasonable DIff algorithm. The code tries to avoid direct DOM operation, but to operate data, and the framework deals with the conversion from “virtual DOM” to “real DOM” according to data changes.

However, this does not mean that the DOM is not needed, nor is it a reason for people to ignore it, and there are even situations where DOM manipulation is the only way, so mastering dom-related knowledge is still a requirement of modern front-end development.

Document

In the browser, the document object, which represents the entire HTML page, is an attribute of the Window object and is therefore a global object.

Document information

The Document object contains common page information, such as the URL, domain, and referrer.

  • URL Contains the full URL of the current page
  • Domain Contains the domain name of the page
  • The referrer contains the URL of the page that links to the current page. If the current page has no source, the referrer property contains an empty string.

All of this information is available in the HTTP header of the request, but is exposed in JavaScript through these attributes.

Of these properties, only the domain property can be set. However, for security reasons, you cannot set a value that is not included in the URL.

Setting document.domain is useful when the page contains panes or inline panes

Document writing

The Document object has an old, less commonly used ability to write content to a web page. There are four methods: write(), writeln(), open(), and close().

The write() and writeln() methods both take a string argument that can be written to a web page. Write () simply writes text, while writeln() also appends a newline character (\n) to the end of the string. These two methods can be used to dynamically add content during page loading. If you want to script something to the browser as quickly as possible, write() is preferred.

One thing to note, though, is that document.write() can be output to a document during page rendering, but if you call Document.write () after the page has loaded, the output will rewrite the entire page, such as in the onload event callback. Be careful.

document.write('hello world')
Copy the code

Talk about the whole game, to see the specific node.

DOM node

Each page is a tree of elements, consisting of many nodes, all of which inherit from the Node type and share basic properties and methods.

The node type

Each node has its own type, such as element node and text node. The mapping between nodeType and common node types is as follows:

  • Elements: 1.
  • Properties: 2
  • Text: 3
  • Note: 8

To get the node type of a div on the page, use the following code:

let div = document.getElementsByTagName("div")[0];
div.nodeType  //1
Copy the code

Note that whitespace and line breaks are also counted as nodes and treated as text nodes.

In addition to nodeType, nodeName and nodeValue can also be used to perform more specific queries on nodes, but do not always return a reasonable value. It is best to determine the nodeType before performing operations.

Relationship between nodes

Child nodes

ChildNodes is a collection of childNodes of an element. Each node has one childNodes that contains an instance of NodeList. NodeList is an array-like object for storing ordered nodes that can be accessed by location.

The NodeList object is unique in that it is a query of the DOM structure, so changes to the DOM structure are automatically reflected in NodeList.

Elements in nodeList can be accessed in two ways — brackets and item().

let firstChild = parent.childNodes[0]
let firstChild = parent.childNodes.item(0)
Copy the code

Most developers prefer to use brackets, more like accessing an array item.

The parent node

Each node has a parentNode attribute that points to its parent element in the DOM tree.

Brother nodes

Use previousSibling and nextSibling to navigate between nodes with null previousSibling for the first node and null nextSibling for the last node.

First and last nodes

FirstChild and lastChild refer to the first and lastChild nodes in childNodes, respectively.

With these relational Pointers, you can access almost any node in the document tree, and this convenience is the highlight of childNodes.

Sentenced to empty

Another method is hasChildNodes(), which returns true to indicate that the node has one or more children. This method is definitely more convenient than querying the length property of childNodes.

Element localization

Whether you are querying or manipulating the DOM, you first need to get the target element, and fortunately, it provides a variety of methods for developers.

  • GetElementById () : Takes the ID of the element as an argument and returns the first element with the same ID if there are multiple elements in the page.

  • GetElementsByTagName () : Takes the tag name of the element as an argument and returns a NodeList containing zero or more elements.

  • GetElementsByName () : Takes the name attribute value as an argument and returns all elements with the given name attribute.

In addition, the Document object has some special properties that represent specific collections:

Document. Anchors: Contain all the elements in your document that have the name attribute

Document. forms: Contains all

elements in a document

Document.images: Contains all elements in the document

Document.links: Contains all elements in the document with the href attribute

You can locate elements by Id, TagName, and Name, but not by class. Yes, there was no way to locate elements by class in the early standard until the HTML5 version.

  • GetElementsByClassName () : Takes the element’s class name as an argument and returns NodeList containing zero or more elements. This method was a late addition to the standard and was compatible in the early years.

In addition, there is also a concern about the classList attribute, according to the business logic to change the style of the element, the need to manipulate the class is very common, before HTML5, we can manipulate the className, but the className is a string, need to split, modify, reassign, slightly tedious. ClassList provides a simpler and more secure implementation.

  • Add (value) to add value to the class list. If it already exists, do nothing.
  • Contains (value), which returns a Boolean value indicating whether the given value exists.
  • Remove (value) to remove the specified value from the class list.
  • Toggle (value), if value already exists in the class list, then delete it; If no, add it.

Those of you who have used Jquery should be familiar with this, but it was not as easy to do in the early days of the native. Now it is.

Once you have the classList attribute, you don’t need the className attribute unless you completely remove or override the element’s class attribute. IE10 and later and other major browsers implement classList attributes.

While Jquery has been mentioned, the Selectors API has been used to locate elements. The new W3C standard provides a jquery-like CSS query API for Selectors.

  • QuerySelector () : Takes the CSS selector argument and returns the first descendant element that matches the pattern.

  • QuerySelectorAll () : a static instance of NodeList that takes an argument to query and returns all matching nodes.

Tags, IDS, and classes are all CSS selectors, so instead of using three different methods, the new API only needs one. In addition, it also supports descendant elements, which is a great convenience.

Note that querySelectorAll returns a static “snapshot” rather than a “live” query. Such an underlying implementation avoids the performance problems that might be caused by using NodeList objects.

There is a final member, matches(), which takes a CSS selector argument and returns true if the element matches it and false otherwise.

Element traversal

Sometimes we need to iterate over and manipulate child elements. Each element can have any number of children and descendants, and the element itself can be a child of another element.

The childNodes property contains all of the childNodes of the element, which could be other elements, text nodes, comments, or processing instructions. There are significant differences in how browsers recognize these nodes.

Here’s a classic example:

<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
Copy the code

When parsing the code above, the UL element will contain seven child elements, three li elements, and four Text nodes (Spaces around the li element). If you remove Spaces between elements, all browsers return the same number of child nodes.

To operate on element nodes in this case, we used to determine the type of node by nodeType once and then proceed.

There are two new options;

1. Element Traversal specification

The Element Traversal API adds five attributes to the DOM Element:

  • ChildElementCount, number of child elements;
  • FirstElementChild, a child of the firstElement type;
  • LastElementChild, a child of the lastElement type;
  • PreviousElementSibling, sibling of the previousElement type;
  • NextElementSibling, a sibling of the latter Element type.

2, the children

What is the difference between Children and childNodes?

You are right, caught off guard is an interview question, I have encountered, do not look down you can answer it?

Why do you need children when you have childNodes to get all the children of an element? In fact, it was differences in the way that previous versions of IE9 handled blank text nodes compared to other browsers that led to the children property.

The children property is an HTMLCollection that contains only child nodes of the element type. This helps developers filter out other types of nodes.

In modern browsers, all DOM elements have these properties, and with the Element Traversal API and the children property, you don’t have to worry about the possibility of a node being selected incorrectly.

Operation node

Positioning and traversal are all about finding nodes, called “searching,” and interacting with the DOM requires “adding, deleting, and changing.”

  • Create – the createElement method ()

The most common way to create a DOM is to create elements like this:

let newNode = document.createElement('div')
Copy the code
  • Tail — increasing the appendChild ()

Add nodes at the end of the childNodes list. The appendChild() method returns the newly added node.

let resNode = parentNode.appendChild(newNode)
Copy the code

Note that if you pass an existing node in the document to appendChild(), the node will be moved from its previous location to the new location, i.e. a node will not be in more than one place in the document at the same time.

  • Former increase – the insertBefore ()

If you want to put a node at a specific location in childNodes instead of at the end, use the insertBefore() method. This method takes two parameters: the node to add and the reference node. When this method is called, the node to be added becomes the previous sibling of the reference node and is returned.

let resNode = parentNode.insertBefore(newNode,targetNode)
Copy the code

If you have a forward increment, how do you realize a backward increment? This is also a classic interview question

  • Replace – the replaceChild ()

AppendChild () and insertBefore() do not delete any existing nodes when they are inserted. In contrast, the replaceChild() method takes two parameters: the node to be inserted and the node to be replaced. The node to be replaced is returned and completely removed from the document tree, and the node to be inserted is replaced.

let resNode = parentNode.replaceChild(newNode,targetNode)
Copy the code
  • Remove – removeChild ()

To remove nodes rather than replace them, use the removeChild() method. This method takes one parameter, the node to remove. The removed node is returned.

let resNode = parentNode.removeChild(oldNode)
Copy the code
  • Cloning – cloneNode ()

All node types also share two methods. The first is cloneNode(), which returns the exact same node as the one that called it. The cloneNode() method takes a Boolean parameter indicating whether deep replication is possible. When the true argument is passed, a deep copy is made, that is, the node and its entire DOM tree are copied. If false is passed, only the node that called the method is copied.

Let resNode = targetnode. cloneNode(true) // deep replication targetNodeCopy the code

The ps: cloneNode() method does not copy JavaScript properties added to DOM nodes, such as event handlers, only HTML properties, and optionally child nodes, but nothing else.

  • normalize()

The final method is normalize(). Its sole task is to process text nodes in the document subtree.

Because of differences in parser implementations or DOM manipulation, there may be text nodes that do not contain text, or text nodes that are siblings of each other. Calling normalize() on a node checks all descendants of the node to search for both cases. If an empty text node is found, it is deleted. If two sibling nodes are adjacent, they are merged into a single text node.

  • The batch operation

At this point, you’ll notice that it’s easier (and faster) to insert an HTML string, innerHTML attribute, than to create a bunch of nodes and then concatenate them in the correct order.

When the browser reads the innerHTML attribute, it returns the HTML string of all the descendants of the element, including the element, comments, and text nodes. When the innerHTML is written, all the nodes previously contained in the element are replaced with a new DOM subtree based on the supplied string value.

let newNode = document.createElement('div')
newNode.innerHTML = '<div><header></header><div></div><footer></footer></div>'
Copy the code

In write mode, the value assigned to the innerHTML attribute is parsed into a DOM subtree, replacing all nodes before the element.

The assigned value defaults to HTML, and all tags in it are converted to elements the way the browser handles HTML. If the assignment does not contain any HTML tags, a text node is generated directly.

Advantages: the advantage of this approach is that it is easier to insert a lot of HTML, the HTML parser is low-level code in the browser (usually C++), and is much faster than JavaScript.

Disadvantages: Frequent operations cause performance loss (you can build strings first and merge operations into one to optimize); The element to be replaced, if there are bound event handlers or other object attributes, the relationship is stuck in memory (preferably manually deleted before operation); May leave users open to XSS attacks (user-input data should not be injected into web pages in this way).

After the big operation, it’s time to look at the operation on the node itself.

  • Modify the

We categorized them into two categories — modifying properties and modifying styles.

Styles are also attributes, but they are slightly different for operational purposes.

The style of the element can be either external to the stylesheet or inline. If the style is external, it is usually changed by class, as mentioned above. If the style is inline, it is changed by the style attribute.

var div = document.getElementsByTagName("div")[0];
    div.style.width="100px";
    div.style.height="100px";
    div.style.backgroundColor="red";
Copy the code

Get the target node first, and then change the style using the dot method. Note that the properties represented by the “-” line in the CSS should be camel case (backgroundColor in the example).

You can also use the cssText attribute, which is relatively fast, if you change multiple files in batches at once.

div.style.cssText = 'width:100px; height:100px; backgroud-color:red'Copy the code

However, style has a drawback. In the read state, it can only get the inline style, not the actual style. What is true representation? That is, the appearance of an element influenced by style rules from multiple sources.

There is a method that can help us do this: getComputedStyle, which is a global hanging method, used as follows:

GetComputedStyle (ele,' optional ')Copy the code

This method takes two arguments: the element to get the style from and a pseudo-element string (such as “:after”). The second argument can be passed null if you do not need to query for pseudo-elements. The getComputedStyle() method returns the element’s computed style.

Because the computed style contains the result of all the styles together, even the information in the browser’s internal style sheet, it can seem a lot. If you only need to get the value of some items, use the dot operator, which is not described here.

So much for style manipulation in everyday use, let’s look at properties other than styles.

Of course, nothing special, just get and set.

  • Point of operation

A normal property is also a property, so you can use a little manipulation, like if we take an input field element and set it to disabled, we can do this.

let ipt = document.querySelector('ipt')
    ipt.disabled = true
Copy the code
  • Get/set methods
let ipt = document.querySelector('ipt')
    ipt.getAttribute('disabled')  // false
    ipt.setAttribute('disabled',true)
    ipt.getAttribute('disabled')  // true
Copy the code

conclusion

That’s enough, but this is just the tip of the iceberg of a complete DOM architecture. Here are some of the most common and commonly used ones.

DOM, this article title is strong because almost all things associated with it on the web, have mastered it, is equivalent to seize the “pulse” of a web page, what kind of elements, element should be how to change, how to get a specific element contains the data and have the ability, how to more friendly and web interaction, are based on in-depth grasp of the DOM.

Even though today’s programming tends to be frame-based, template-based, data-driven, and not all-encompassing, what about capabilities that frameworks don’t have? What if we want to use a particular capability in the component library? If you look up, you can see a little bit of DOM, which is the foundation.

Because there are many connections, this part is divided into two parts, but it may not cover everything, welcome to exchange.

Powerful DOM (Part 1)

Series of articles:

【 Talk about the front end 】 good basic skills, easy to learn with me

Small role, big use — variable

Why is everything an object?

[Talking about the front end] Those “unreasonable value” operations

Digital games in JavaScript

【 Talk about front-end 】 “string” jianghu

【 Talk about the front end 】 Before there is “object”

【 Talk about the front end 】 After “object”

Arrays are the cornerstone of advanced data structures

The first-class citizens of the JavaScript world — functions