admin管理员组

文章数量:1277346

I am tired of including jquery in simple projects but I am so used to using it and I am trying to break free form my dependency on it. I am trying to create a function that will give the same feel of getting selectors like classes and tags. Example: $('selector').innerHTML = ".something";. I have just been looping through them one by one like so:

var classElements = document.querySelectorAll('.something');
for (var i = classElements.length - 1; i >= 0; i--) {
   classElements[i].innerHTML = "This Is A Div";
} 

But I wanted to create a function where I could just loop through a selector without having to write out a for loop for everything that I want to find. So I could just write it our like above $('.something').innerHTML = "something";

So far this is what I have but it will only get the first of each selector and won't get all of them. Needless to say I am very stuck and the more I read on the subject the more confused I get. I was wondering if someone could point me in the right direction where my thinking is flawed or explain how jquery goes about doing this. Here is my code:

window.getElements = function(selector) {
    var selectors = document.querySelectorAll(selector);
    for (var i = selectors.length - 1; i >= 0; i--) {
        var elements = selectors[i];
    }
    return elements;
};

getElements(".something").innerHTML = "something";

Here is a fiddle Fiddle

I am tired of including jquery in simple projects but I am so used to using it and I am trying to break free form my dependency on it. I am trying to create a function that will give the same feel of getting selectors like classes and tags. Example: $('selector').innerHTML = ".something";. I have just been looping through them one by one like so:

var classElements = document.querySelectorAll('.something');
for (var i = classElements.length - 1; i >= 0; i--) {
   classElements[i].innerHTML = "This Is A Div";
} 

But I wanted to create a function where I could just loop through a selector without having to write out a for loop for everything that I want to find. So I could just write it our like above $('.something').innerHTML = "something";

So far this is what I have but it will only get the first of each selector and won't get all of them. Needless to say I am very stuck and the more I read on the subject the more confused I get. I was wondering if someone could point me in the right direction where my thinking is flawed or explain how jquery goes about doing this. Here is my code:

window.getElements = function(selector) {
    var selectors = document.querySelectorAll(selector);
    for (var i = selectors.length - 1; i >= 0; i--) {
        var elements = selectors[i];
    }
    return elements;
};

getElements(".something").innerHTML = "something";

Here is a fiddle Fiddle

Share Improve this question asked Feb 20, 2017 at 0:44 user3331344user3331344 9911 gold badge15 silver badges34 bronze badges 12
  • How often do you need to assign the same HTML to a bunch of elements at the same time? – Ry- Commented Feb 20, 2017 at 0:47
  • 1 Use slim version of jQuery that only includes the parts you want – charlietfl Commented Feb 20, 2017 at 0:50
  • Not matter what size list querySelectorAll() returns, the end of your for loop sets elements to selectors[0], which you return. So this function can only every return selectors[0]. – david25272 Commented Feb 20, 2017 at 0:51
  • 2 If you want it to look exactly the same as jQuery, use jQuery. – Ry- Commented Feb 20, 2017 at 0:54
  • 1 If you want to break away from jQuery, then break away from it. Learn to write short, clean code in a style that uses the features you have available natively. – user1106925 Commented Feb 20, 2017 at 1:01
 |  Show 7 more ments

6 Answers 6

Reset to default 7

Here is how you would do it. I have done what you have asked which is allow you to use all the native functionality rather than coin wrappers around it. jQuery returns its own api which acts on the selectors. What I have done is create a selector which allows you to act on each element it finds

window.getElements = function(selector,cb) {
    var selectors = document.querySelectorAll(selector);
    [].forEach.call(selectors, cb);
};

getElements(".something", function(el){el.innerHTML = "ha"});

getElements("#one", function(el){el.style.background = "red" });

It takes the dom list that is found, converts it into an array and then calls your passed function where you pass your native code

Here is a fiddle

https://jsfiddle/y52f4wh8/5/

Jquery works differently:

window.jquery = function(selector,cb) {
	var selectors = document.querySelectorAll(selector);
    
    function mand(cb) {
	   [].forEach.call(selectors, cb);
	};
    // Here we return our own api that uses the mand function to act on
    // our selected list.
    return {
     html: function(str){
     	mand(function(el){
      	el.innerHTML=str;
      });
      
     },
     bg: function(color){
     	mand(function(el){
      	el.style.background = color; 
      });
     }
    }
};
// The jquery way!
jquery(".something").html("ha");

getElements(".something").innerHTML = "something";

this does not work because that your function gets and returns all of the elements, which is a NodeList, but it does not automatically apply methods to every element in the collection as jQuery does. In order to do that, you would have to convert the elements to an array and actually call the function on each element using a loop or some other function.

EDIT: To be clear, you cannot just call NodeList.innerHTML = '' on a NodeList because innerHTML is applied to one element. jQuery internally takes care of BOTH of the collecting of elements, and the applying of methods for you.

EDIT #2: After examining your function more carefully, I have realized there are other issues, but what I wrote above is still the basis from which you want to spring.

You could use something like this for getting elements?:

function getElements(elements) {
    return [...querySelectorAll(elements)]
}

But applying functions on nodes is going to be more selective on a case-by-case basis since many of them are applied differently.

The selector part of JQuery is called Sizzle. It has all the functionality that you need but does not e with the other parts of JQuery.

If you would like to find out more about the javascript behind it, I remend to take a look at the sourcefiles of Sizzle.

Jquery like methods without jquery.

What is left :)

children find parents parent closest , next prev before after , first last eq() , each ,.hasClass ,prop .removeProp ,val,width height

<link rel="stylesheet" href="https://cdn.jsdelivr/npm/[email protected]/dist/css/bootstrap.min.css">

<div class="p-4">
    <div id="dd" class="aa p-5 border">AAAAA</div>
</div>
<script>
function cn(x=''){
    console.log(x);
}
window.$ = function(selector) {
    
    if(typeof selector=='string')
        var selectors = document.querySelectorAll(selector);
    else selectors=selector;
    
    var doo = function (callback){
        [].forEach.call(selectors, callback);
        return $(selector);
    };
    
    // Here we return our own api 
    return {
        html: function(x){
            return doo(function(el){
                el.innerHTML=x;
            });
        },      
        text: function(x){
            return doo(function(el){
                el.innerText=x;
            });
        },
        bg: function(x){
            return doo(function(el){
                el.style.background = x; 
            });
        }
        ,toggleClass: function(x){
            return doo(function(el){
                let xre=new RegExp(' '+x+' ','gm');
                if( (' '+el.className+' ').match(xre)){
                    el.className = (' '+el.className+' ').replace(' '+x+' ',x).trim();
                }else{
                    el.className = el.className+' '+x;
                }
            });
        }
        ,addClass: function(x){//
            return doo(function(el){
                el.className = el.className.trim()+' '+x;
            });
        }
        ,removeClass: function(x){//
            return doo(function(el){
                el.className = (' '+el.className+' ').replace(' '+x+' ',x).trim();
            });
        }
        
        ,attr: function(x,y){
            return doo(function(el){
                el.setAttribute(x,y);
            });
        }           
        ,removeAttr: function(x){
            return doo(function(el){
                el.removeAttribute(x);
            });
        }           
        ,data: function(x,y){
            return doo(function(el){
                el.setAttribute('data-'+x,y);
            });
        }       
        ,remove: function(x){
            return doo(function(el){
                el.remove();
            });
        }
        ,ac: function(x){return $(selector).addClass(x)}
        ,rc: function(x){return $(selector).removeClass(x)}
        ,tc: function(x){return $(selector).toggleClass(x)}
        ,yours: function(x){
            return doo(function(el){
                //bla bla
            });
        }
    }
};


$(".aa").addClass('bg-primary text-white rounded m-4').html("BBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB")
</script>

jQuery is essentially a wrapper object for NodeList which adds more functionality to DOM operations. If you want to create your own wrapper object which defines functions for bulk versions of all the Element API, you are free to do so, but then you might as well use jQuery or some derivative.

If you want an extremely lightweight proxy object for doing bulk operations on DOM elements, there is the Proxy object in ES6 which can make this very easy to do, but has no IE support.

const $ = function(selector) {
  const nodeList = document.querySelectorAll(selector);
  return new Proxy(nodeList, {
    set: function(target, property, value) {
      for (let i = 0; i < target.length; i++) {
        target[i][property] = value;
      }
    },
    get: function(target, property) {
      return target[0] && target[0][property];
    }
  });
};

console.log($('p').innerHTML);
$('p').innerHTML = 'Bulk assignement!';
<p>A B C</p>
<p>1 2 3</p>
<p>Do Re Mi</p>

An approach which would be best avoided is to define a setter for innerHTML on NodeList.

Object.defineProperty(NodeList.prototype, 'innerHTML', {
  set(text) {
    [...this].forEach(elt => elt.innerHTML = text);
  }
});

const $ = selector => document.querySelectorAll(selector);

$('.foo').innerHTML = "it works";
<div class="foo"></div>
<div class="foo"></div>

本文标签: loopsCreate a function to get selectors like jquery does with pure javascriptStack Overflow