Reputation: 825
In jQuery, we can run multiple methods within a single statement in order to efficiently express the jQuery code:
$("#p1").css("color", "red").html("Hello world!").attr("class","democlass");
And how about Javascript?
document.getElementById("p1").style.color = "red";
document.getElementById("p1").innerHTML = "Hello world!";
document.getElementById("p1").setAttribute("class","democlass");
Upvotes: 0
Views: 86
Reputation: 6366
If you want to write jQuery like chaining, the trick is to limit the amount of times the DOM is touched and control when to apply changes. Something like this will do that:
/**
* Global variable for closed scope functions
*
* @param {HTMLElement} node
* @returns myElementTreaterCls
*/
var notjQuery = (function() {
var myElementTreaterCls = (function() {
/**
* Creates an instance of myElementTreaterCls.
*
* @param {HTMLElement} node
*
* @memberOf myElementTreaterCls
*/
function myElementTreaterCls(node) {
this.node = node;
/**
* Styling changes
*
* @type {string}
* @memberOf myElementTreaterCls
*/
this.currentCss = null;
}
/**
* Applies all changes to the DOM element
*
* @returns myElementTreaterCls
*
* @memberOf myElementTreaterCls
*/
myElementTreaterCls.prototype.render = function() {
if (this.currentCss != null) {
this.node.style.cssText = this.currentCss;
this.currentCss = null;
}
return this;
};
/**
* Add styling rules to the DOM element
* If "render" is falsy the rules aren't applied, saving a paint
*
* @param {any} [rules={}]
* @param {boolean} [render=true]
* @returns myElementTreaterCls
*
* @memberOf myElementTreaterCls
*/
myElementTreaterCls.prototype.addCss = function(rules, render) {
if (rules === void 0) {
rules = {};
}
if (render === void 0) {
render = true;
}
if (this.currentCss === null) {
this.currentCss = this.node.style.cssText.toString();
}
for (var cssRule in rules) {
if (rules.hasOwnProperty(cssRule)) {
var rule = rules[cssRule];
this.currentCss += " " + cssRule + ": " + rule + ";";
}
}
if (render === true) {
this.render();
}
return this;
};
return myElementTreaterCls;
}());
//Returns Instantiate function to "notjQuery"
return function myElementTreater(node) {
return new myElementTreaterCls(node);
};
})();
And here is a use example:
//Minified version of the "notjQuery" code:
var notjQuery=function(){var t=function(){function t(t){this.node=t,this.currentCss=null}return t.prototype.render=function(){return null!=this.currentCss&&(this.node.style.cssText=this.currentCss,this.currentCss=null),this},t.prototype.addCss=function(t,r){void 0===t&&(t={}),void 0===r&&(r=!0),null===this.currentCss&&(this.currentCss=this.node.style.cssText.toString());for(var n in t)if(t.hasOwnProperty(n)){var s=t[n];this.currentCss+=" "+n+": "+s+";"}return r===!0&&this.render(),this},t}();return function(r){return new t(r)}}();
//>>TEST<<//
//Setup node
var n = document.createElement("p");
n.innerHTML = "TEST PARAGRAPH";
n.style.color = "red";
document.body.appendChild(n);
//Instantiate, make change but delay applying them
var el = notjQuery(n)
.addCss({
"float": "right",
right: "20px",
color: "green"
}, false);
//Make changes many times in a loop, which should cause a lot of repaints, but doesn't because we delay applying them
var i = 0,
interval;
interval = setInterval(function() {
i++;
if (i < 100) {
el.addCss({
right: i + "px",
display: (i % 2 ? "block" : "none")
}, false);
} else {
//Stop loop
clearInterval(interval);
//Finally applying rules to node
el.render();
}
}, 1);
Of course this is just to prove the concept.
Be mindful of the DOM!
Upvotes: 0
Reputation: 97928
The performance gain is simply because you are only searching for the element once, and then storing it in a variable. jQuery makes this easy by returning that variable to you repeatedly, but with or without jQuery, you can just use an explicit variable for the same effect.
Without jQuery:
var p1 = document.getElementById("p1");
p1.style.color = "red";
p1.innerHTML = "Hello world!";
p1.setAttribute("class","democlass");
With jQuery:
var p1 = $("#p1");
p1.css("color", "red");
p1.html("Hello world!");
p1.attr("class","democlass");
Upvotes: 1
Reputation: 5084
The performance enhancement we should never forget is to look for the element in the DOM only once when possible:
var p1 = document.getElementById("p1");
p1.style.color = "red";
p1.innerHTML = "Hello world!";
p1.setAttribute("class","democlass");
Upvotes: 1
Reputation: 337646
Note that method chaining in jQuery make zero difference to performance. It's just syntactic sugar to make the code shorter and prettier.
That said you can make a marginal improvement to your JS code by storing the p1
element in a variable, and also using the classList
object to add/remove classes, like this:
var p1 = document.getElementById("p1");
p1.style.color = "red";
p1.innerHTML = "Hello world!";
p1.classList.add('democlass');
Upvotes: 1