review

This article will focus on extending the functionality of the jQuery API to make it more powerful. This article will focus on extending the functionality of the jQuery API to make it more powerful.

The following is the code used in this exercise, based on the first article, using addClass() as an example.

<ul>
  <li id="item1">item1</li>
  <li id="item2">item2</li>
  <li id="item3">item3</li>
  <li id="item4">item4</li>
  <li id="item5">item5</li>
</ul>

.red{
  color:red;
}

window.simpleTools = function(node){
  return{
    addClass:function(classes){ classes.forEach((value) => node.classList.add(value)); }}; };Copy the code

Thought 1: What if the pass parameter is a selector?

Solution:

Add a type judgment to solve it! To make our code more semantic, rename the passed argument from node to nodeOrSelector, and define a node variable in the function. If the passed argument is a selector, use document.querySelector() to find the corresponding node and assign it to node. If the parameter is not a selector, assign it directly to Node and store it.

 var node;
 if(typeof nodeOrSelector === 'string'){
    node = document.querySelector(nodeOrSelector);
 }else{
    node = nodeOrSelector;
 }
Copy the code

Test run:

var nodeTest = simpleTools('#item3');
nodeTest.addClass(['red']);
console.log(document.querySelectorAll('#item3'));
Copy the code

Thought 2: What if the parameter is passed with multiple selectors?

Solution:

  1. thedocument.querySelector( )todocument.querySelectorAll( ), the variable node becomes a Nodes object.
  2. Iterate over Nodes and add red in order
window.simpleTools = function(nodeOrSelector){
  var nodes = {};
  if(typeof nodeOrSelector === 'string'){
    nodes = document.querySelectorAll(nodeOrSelector);
  }else{
    nodes = nodeOrSelector;
  }
  return{
    addClass:function(classes){
      classes.forEach((value) =>{
      for(var i = 0;i < nodes.length;i++){
        nodes[i].classList.add(value);
      }
      });
    }
  };
};
Copy the code

Test run:

var nodeTest = simpleTools('ul>li');
nodeTest.addClass(['red']);
console.log(document.querySelectorAll('ul>li'))
Copy the code

var nodeTest2 = simpleTools('#item3');
nodeTest2.addClass(['red']);
console.log(document.querySelectorAll('#item3'))
Copy the code

Thought 3: What if you want to change the prototype chain?

Now nodes is an Object connected to Nodelist. prototype. I want my prototype chain to be object. prototype.

Solution:

With a temporary variable, loop through to get a pure object.

window.simpleTools = function(nodeOrSelector){
  var nodes = {};
  if(typeof nodeOrSelector === 'string'){
    var temp = document.querySelectorAll(nodeOrSelector);
    for(var i =0 ; i<temp.length; i++){ nodes[i] = temp[i]; } nodes.length = temp.length; }else if(nodeOrSelector instanceof Node){
    nodes = {
      0 :nodeOrSelector,
      length :1
    };
  }
  returnnodes; // Just look at the nodes changes, ignoring the addClass() method for now;Copy the code

If there are multiple selectors, traverse and save, and don’t forget nodes.length. If it’s a node, you also need to construct a nodeOrSelector to store it in the node object in the same form as the branch above. Now either multiple selectors or a node has been converted to link object.prototype only.

Test run:

var nodeTest = simpleTools('#item3');
console.log(nodeTest);
Copy the code

var nodeTest2 = simpleTools('ul>li');
console.log(nodeTest2);
Copy the code

Thought 4: How to set the text?

To get text, store the textContent for each item in Nodes.

getText : function(){
    var texts = [];
    for(var i = 0; i < nodes.length; i++){ texts.push(nodes[i].textContent); }return texts;
}
Copy the code

If it is set text, the text to be set is assigned to textContent in turn by iterating through.

setText : function(text){
    for(var i = 0; i < nodes.length; i++){ nodes[i].textContent = text; }return text;
}
Copy the code

Test run:

var nodeTest = simpleTools('#item3');
nodeTest.setText('hello');
Copy the code

Code optimization

The code above looks so similar, both in setup and fetch, that there is potential for optimization. We’re trying to combine these two functions into one, so if you pass in arguments, you need to set text, and if no arguments are passed in, you want to get text.

text: function (text) {
    if (text == undefined) {
        var texts = [];
        for (var i = 0; i < nodes.length; i++) {
                texts.push(nodes[i].textContent);
            }
        return texts;
    }
    else {
        for(var i = 0; i < nodes.length; i++) { nodes[i].textContent = text; }}}Copy the code

Give me another alias

window.$ = function simpleTools() {... }Copy the code

Using the global variable $is equivalent to using simpleTools.

If a variable is constructed from jQuery, add a $before the variable to prevent confusion.

Eg: Var $node = $(#item3)

Two forms of return

The first kind of

window.$ = function simpleTools(nodeOrSelector) {
    var nodes = {};
    if (typeof nodeOrSelector === 'string') {
        var temp = document.querySelectorAll(nodeOrSelector);
        for (var i = 0; i < temp.length; i++) {
            nodes[i] = temp[i];
        }
        nodes.length = temp.length;
    } else if (nodeOrSelector instanceof Node) {
        nodes = {
            0 : nodeOrSelector,
            length: 1
        };
    }

    return {
        addClass: function(classes) {
            classes.forEach((value) =>{
                for(var i = 0; i < nodes.length; i++) { nodes[i].classList.add(value); }}); }, text:function(text) {
            if (text == undefined) {
                var texts = [];
                for (var i = 0; i < nodes.length; i++) {
                    texts.push(nodes[i].textContent);
                }
                return texts;
            } else {
                for(var i = 0; i < nodes.length; i++) { nodes[i].textContent = text; }}}}; };Copy the code

The second,

window.$ = function simpleTools(nodeOrSelector) {
    var nodes = {};
    if (typeof nodeOrSelector === 'string') {
        var temp = document.querySelectorAll(nodeOrSelector);
        for (var i = 0; i < temp.length; i++) {
            nodes[i] = temp[i];
        }
        nodes.length = temp.length;
    } else if (nodeOrSelector instanceof Node) {
        nodes = {
            0 : nodeOrSelector,
            length: 1
        };
    }

    nodes.addClass = function(classes) {
        classes.forEach((value) =>{
            for(var i = 0; i < nodes.length; i++) { nodes[i].classList.add(value); }}); }; nodes.text =function(text) {
        if (text == undefined) {
            var texts = [];
            for (var i = 0; i < nodes.length; i++) {
                texts.push(nodes[i].textContent);
            }
            return texts;
        } else {
            for(var i = 0; i < nodes.length; i++) { nodes[i].textContent = text; }}};return nodes;
};

Copy the code

You may choose whichever you like

summary

  1. AddClass () extends its addClass() method to not only pass nodes, but also accept selectors.
  2. Further deepen the understanding of the prototype chain.

Try writing your own API!