1. Encapsulate functions
1.1 Getting node sibling Elements
1.1.1 Original code
<ul>
<li id="item1"> Option 1</li> <li id="item2"> Option 2</li> <li id="item3"> Option 3</li> <li id="item4"> Option 4</li> <li id="item5"> Option 5</li> </ul>let allChildren = item3.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == Item3) {array[array.length] = allChildren[I] array.length += 1}} console.log(array) // Gets a pseudo-array of sibling elements of Items3Copy the code
1.1.2 Wrap the function and get the API, getSiblings()
functionGetSiblings (node) {// This is the APIlet allChildren = node.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == node) { array[array.length] = allChildren[i] array.length += 1 } }returnArray} console.log(getSiblings(item3)) // Gets siblings of Items3Copy the code
1.2 Write the second function to add style to the element
1.2.1 Original code
let classes = {'a':true.'b':false.'c':true}
for (let key inClasses) {// iterate over the hash tablelet value = classes[key]
if(value) {// value is true to add, false to delete node.classlist.add (key)}else {
node.classList.remove(key)
}
}
Copy the code
1.2.2 Encapsulating functions to get the second API, addClass()
function addClass(node, classes) {
for (let key in classes) {
let value = classes[key]
if (value) {
node.classList.add(key)
} else {
node.classList.remove(key)
}
}
}
addClass(item3, {a:true,b:false,c:true})
Copy the code
1.2.3 Code optimization
As long as there is similar code, there is room for optimization.
function addClass(node, classes) {
for (let key in classes) {
let value = classes[key]
let methodName = value ? 'add':'remove'// If value is true, methodName is add, and false is Remove node.classList.['methodName'](key)
}
}
ffdom.addClass(item3, {a:true,b:false,c:true})
Copy the code
1.2.4 Change to an array
function addClass(node, classes) {
classes.forEach((value)=> node.classList.add(value))
}
addClass(item3, ['a'.'b'.'c'])
Copy the code
2. Associate two independent function namespaces
You can also prevent code coverage problems by associating two independent functions with the namespace design pattern.
Window.xxxxdom = {} /*yui uses the namespace mode */ xxxxdom.getsiblings =function(node) {
let allChildren = node.parentNode.children
letArray = {// pseudo-array length: 0}for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == node) {array[array.length] = allChildren[I]return array
}
xxxxdom.addClass = function(node, classes) {
classes.forEach((value)=> node.classList.add(value))
}
xxxxdom .getSiblings(items)
xxxxdom .addClass(item3, ['a'.'b'.'c'])
Copy the code
3. Remove xxxxdom
Remove the XXXXDOM and rewrite it into the following pattern. We have two methods.
item3.getSiblings()
item3.addClass(['a'.'b'.'c'])
Copy the code
3.1 The first method is to modify the node prototype directly
The downside: there are code coverage issues.
Node.prototype.getSiblings = function() {
letAllChildren = this.parentNode.children // this implicitly refers to Nodelet array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == this) { array[array.length] = allChildren[i] array.length += 1 } }return array
}
Node.prototype.addClass = function(classes) { classes.forEach((value)=> this.classList.add(value)) } console.log(item3.getSiblings()) // Get a pseudo-array of sibling elements of Item3. AddClass (['a'.'b'.'c'])
Copy the code
3.1.1 Function Call, difference between Call and no Call
Use call to specify this explicitly, and this is the first argument instead of specifying this implicitly
item3.getSiblings.call(item3)
item3.addClass.call(item3,['a'.'b'.'c'])
Copy the code
3.2 The second way is to make your own constructor.
Creating your own constructor solves the code coverage problem.
3.2.1 ideas
Create a Node2 constructor that takes a node argument, returns a hash table, and its key is the API we want. When used, pass in the node parameter and it is ready to use.
window.Node2 = function(node) {
return {
getSiblings: function() {
letAllChildren = node.parentNode.children // node is the node parameter passed inlet array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == node) { array[array.length] = allChildren[i] array.length += 1 } }return array
}
addClass: function(classes) {
classes.forEach((value)=> node.classList.add(value))
}
}
}
var node2 = Node2(item3)
node2.getSiblings()
node2.addClass(['a'.'b'.'c']))
Copy the code
3.2.1 Change Node2 to jQuery
Change Node2 to jQuery, where jQuery takes an old DOM and returns a new object with a new API. The internal implementation still calls the old API, but it’s a little nicer. JQuery is essentially a constructor that takes a parameter, which can be a node or selector, and returns a method object to manipulate the node.
window.jQuery = function(node) {
return {
getSiblings: function() {
let allChildren = node.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == node) { array[array.length] = allChildren[i] array.length += 1 } }return array
}
addClass: function(classes) {
classes.forEach((value)=> node.classList.add(value))
}
}
}
var node2 = jQuery(item3)
node2.getSiblings()
node2.addClass(['a'.'b'.'c']))
Copy the code
3.2.2 Improved jQuery, improved parameter passing
A passing node can be not just a node but also a selector, just type checking.
window.jQuery = function(nodeOrSelector) {
let node
if(typeof nodeOrSelector === 'string') {// type check node = document.querySelector(nodeOrSelector)}else {
node = nodeOrSelector
}
return {
getSiblings: function() {
let allChildren = node.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if(allChildren[i] ! == node) { array[array.length] = allChildren[i] array.length += 1 } }return array
}
addClass: function(classes) {
classes.forEach((value)=> node.classList.add(value))
}
}
}
var node2 = jQuery('#item3'Node2.getsiblings () node2.addclass ([)'red'.'b'.'c'])) related CSS css. red {color: red; }Copy the code
3.2.3 Improve jQuery to operate on multiple nodes
window.jQuery = function(nodeOrSelector) {
let nodes
if(typeof nodeOrSelector === 'string') {
letTemp = document. QuerySelectorAll (nodeOrSelector) / / pseudo arrayfor(leti=0; i<temp.length; I ++) {node[I] = temp[I]} nodes.length = temp.else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.getSiblings = function() {}
nodes.addClass = function() {}
return nodes
}
var node2 = jQuery('ul > li')
console.log(node2)
Copy the code
3.2.4 Improve jQuery to add methods to Nodes
window.jQuery = function(nodeOrSelector) {
let nodes
if(typeof nodeOrSelector === 'string') {
letTemp = document. QuerySelectorAll (nodeOrSelector) / / pseudo arrayfor(leti=0; i<temp.length; i++) { node[i] = temp[i] } nodes.length = temp.length object.prototype }else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.addClass = function() {// add the addClass () method classes.foreach ((value)=> {for(let i = 0; i < nodes.length; i++) {
node[i].classList.add(value)
}
}
}
return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['blue'])
Copy the code
3.2.5 Improve jQuery to add additional apis to Nodes
Add getText() and setText()
window.jQuery = function(nodeOrSelector) {
let nodes
if(typeof nodeOrSelector === 'string') {
letTemp = document. QuerySelectorAll (nodeOrSelector) / / pseudo arrayfor(leti=0; i<temp.length; I ++) {node[I] = temp[I]} nodes.length = temp.else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.addClass = function() {
classes.forEach((value)=> {
for(let i = 0; i < nodes.length; i++) {
node[i].classList.add(value)
}
}
}
nodes.getText = function() { // 添加getText()
var texts = []
for(let i = 0; i < nodes.length; i++) {
text.push(nodes[i].textContent)
}
return texts
}
nodes.setText = function() {// addsetText()
for(let i = 0; i < nodes.length: i++) {
nodes[i].textContent = texgt
}
}
return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['blue'])
node2.getText()
node2.setText('hi')
Copy the code
3.2.6 Optimize the Text () API
window.jQuery = function(nodeOrSelector) {
let nodes = {}
if(typeof nodeOrSelector === 'string') {
letTemp = document. QuerySelectorAll (nodeOrSelector) / / pseudo arrayfor(leti=0; i<temp.length; I ++) {node[I] = temp[I]} nodes.length = temp.else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.addClass = function() {
classes.forEach((value)=> {
for(let i = 0; i < nodes.length; i++) {
node[i].classList.add(value)
}
}
}
node2.text = function(text) {// get getText() andsetThe Text ()if(text === undefined) {
var texts = []
for(let i = 0; i < nodes.length; i++) {
text.push(nodes[i].textContent)
}
return texts
}
} else {
for(let i = 0; i < nodes.length: i++) {
nodes[i].textContent = text
}
}
return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['blue'])
console.log(node2.text())
node2.text('hi')
Copy the code
4. To summarize
Create a jQuery constructor that takes a node or selector, wraps it into a pseudo-array, and then adds apis to that pseudo-array to return it.
window.jQuery = function(nodeOrSelector) {
let nodes = {
0: nodeOrSelector,
length: 1
}
nodes.addClass = function(classes) {}
nodes.text = function(text) {}
return nodes
}
var node2 = jQuery('ul > li')
{0: li, 1: li, length: 5, addClass: f, text: f}
node2.addClass(['blue'])
node2.text()
node2[0].classList.add('blue')
Copy the code
Advantages of jQuery:
- JQuery does a good job of compatibility and version 1.7 is compatible with IE 6.
- JQuery also has modules for animation, AJAX, etc., not just DOM manipulation.
- JQuery is much more versatile.
5. Reference links
JQeury related courses https://xiedaimala.com/