Suits the crowd

This article is for front-end developers who are 0.5 to 3 years old, and anyone who wants to know what jQuery is all about.

preface

Talk about personal views on jQuery, no interest can directly see the source analysis.

If you’ve been a developer for more than five years, you know jQuery. It’s like if you had a mobile phone ten years ago, you must know Nokia.

JQuery is definitely on its way out. It’s not as good as the big three. Lonely to what level?

It’s so frustrating that when you bring him up in an interview, the interviewer thinks you’re out of date.

If you use jQuery to write your project, people will think your project is low.

So much so that they didn’t even bother to give him a special section (it would have been a special section ten years ago).

In fact, jQuery still has a lot to learn and can be used for reference, this is the author thought twice, it is one of the reasons for the source code. If you’re looking for a high salary for a short interview, jQuery and this article are obviously not for you. If you pay attention to the basics, take a look at this article.

If you’re starting out in the era of the big three frameworks, it’s easy to think of jQuery as a library of JavaScript functions that allow your project to “write less and do more” than native JS. Yes, document.getelementById (‘id’).innerhtml = “hello” can be implemented using $(‘#id’).html(” hello “), which is much more convenient than writing projects in javascript. He has many advantages, specific advantages, the following analysis of the source code will be summarized. But first of all, what’s his flaw? What is the root of elimination?

My point of view is that the emergence of virtual DOM is the root of the elimination of jQuery. JQuery shorthand, or usage is mindless dom manipulation. When the same DOM needs to be rendered multiple times, if you manipulate the DOM directly (because it is rendered multiple times), it is much less efficient than if you manipulate js directly and then synchronize the DOM with the result (because it only renders the final dom once). The appearance of virtual DOM makes our front end directly convert from MVC structure to MVVM structure. The three major frameworks are data-driven, while jQuery is still the writing method of dom operation, so it has to be eliminated. This is like Nokia trying to save itself in other aspects. If it doesn’t abandon Symbian and replace the popular system, it will be unable to do so and finally give up ruthlessly.

Handwritten mini_jquery

The basic page

Let’s create a new HTML and write what jQuery would say:

</title> <meta name="keywords" content="shopInfo. if_exists" /> <meta name="description" content="shopInfo.shopName? if_exists" /> <meta http-equiv="X-UA-Compatible" content="IE=8"> </meta> <meta http-equiv="Content-Type" content="text/html; Charset = utF-8 "/> <meta name="viewport" content="width=device-width, initial =1.0, maximum-scale=1.0, user-scalable=0"> </head> <body> <script src="src/zQuery.js"></script> </body> </html>Copy the code

Create zquery.js again.

Global registration

If you’ve ever used jquery, you know who we are? Global can be used anywhere. With the introduction of jQuery, $is registered globally. Let’s see how the authorities handle it:

The thumbnail code is shown above. As you can see, jQuery is called globally by understanding how to call function(){})().

So has anyone thought about it? Why is there a module judgment in the screenshot? In fact, that is the subsequent node environment, but also some people need to use jQuery in node, node is not dom page, add judgment. We don’t need to think about that in our case. We hand-write a registration:

(function (window) {
    var zQuery = function () {
        return new Object();
    }
    window.$ = zQuery;
})(window);
Copy the code

Access to the object

That is to complete the import registration, global registration. But what is the object returned? We all know that $(“”) returns a DOM object, which can be fetched by ID, by tag name, by class name, and so on.

  • First he gets the DOM object based on the value in (),
  • Support id, class, tag obtain.

Let’s change its return value by defining an initialization method for it and calling it immediately when it is created:

(function (window) { var zQuery = function () { return new zQuery.fn.init(selector); } window.$ = zQuery; zQuery.fn = { init: function (selector) { this.dom = []; const childNodes = document.childNodes; var rs = null; if (typeof (selector) ! = 'undefined') {if (selector.substr(0, 1) == "#") {//id selector rs = document.getelementById (selectors.slice(1)); this.dom[0] = rs; } else if (selector. Substr (0, 1) = = ". ") {/ / style selector rs = document. The getElementsByClassName (selector. Slice (1)); for (var i = 0; i < rs.length; i++) { this.dom[i] = rs[i]; }} else {/ / tag selector rs = document. GetElementssByTagName (); for (var i = 0; i < rs.length; i++) { this.dom[i] = rs[i]; } } } return this; }, } })(window); This completes the object fetching for $().Copy the code

Action object

Once we have our DOM objects, the next question is how we change them. Common ones are:

  • HTML changes the text value
  • CSS change colors
  • Hide /show Hide or show

The above method, using native JS implementation, is very simple? We embed zquery.fn to implement the code:

zQuery.fn = { ... , html: function (value) { if (this.dom.length == 1) { this.dom[0].innerHTML = value; } else if (this.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style[attr] = value; } } }, css: function (attr, value) { if (this.dom.length == 1) { this.dom[0].style[attr] = value; } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style[attr] = value; } } }, show: function (attr, value) { if (this.dom.length == 1) { this.dom[0].style.display = 'block'; } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style.display = 'block'; } } }, hide: function (attr, value) { if (this.dom.length == 1) { this.dom[0].style.display = 'none'; } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style.display = 'none'; }}}},Copy the code

At this point, our DOM operation is complete. Here are some examples:

<div id="cssId" style="color: black;" <div class="cssSelector"> <div class="cssSelector"> </div> <div class="cssSelector"> <div class="cssSelector"> </div> js: btnList.addEventListener('click', function (e) { var id = e.target.id; The switch (id) {case 'htmlId: $(' # htmlId). The HTML (" HTML assignment success "); break; case 'cssId': $('#cssId').css("color", "red"); break; case 'showId': $("#showId").hide(); break; case 'changeId': $(".cssSelector").css("color", "#0099dd"); break; }}});Copy the code

To complete the chain

One of the great things about jquery is its easy support for chains. So how do we do it?

And that makes sense, because all we have to do is take the DOM object that we’ve found, and go on to the next level of DOM objects until we find the result. We save the dom object for the first time, take the DOM object for the second time, obtain the dom object based on the condition of the first time, and then re-initialize. And this process, all the hierarchies, multiple levels of DOM, built-in methods are consistent, we need to complete the inheritance of the prototype chain.

Three steps:

  • 1. Get the last DOM

  • 2. Obtain the next DOM based on the last DOM.

  • 3. Complete prototype chain inheritance

    As a first step, we can create a new global myDocument that represents the saved DOM structure. zQuery.fn = { init: function (selector, myDocument) { this.dom = this.dom ? this.dom : []; this.myDocument = myDocument ? myDocument : document; const childNodes = this.myDocument.childNodes; var rs = null; if (typeof (selector) ! = 'undefined') {if (selector. Substr (0, 1) = = "#") {/ / id selector rs = this. MyDocument. GetElementById (selector. Slice (1)); this.dom[0] = rs; console.log("rs===" + rs.innerText + rs.innerHTML); } else if (selector. Substr (0, 1) = = ". ") {/ / style selector rs = this. MyDocument. GetElementsByClassName (selector. Slice (1)); for (var i = 0; i < rs.length; i++) { this.dom[i] = rs[i]; } } } return this; },... } Obtain the next DOM based on the last DOM. zQuery.fn = { ... find: function (selector) { if (this.dom.length == 1) { this.init(selector, this.dom[0]); } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.init(selector, this.dom[i]); } } return this; },} // prototype = zquery.fn;Copy the code

Implement case tests:

<div class="f_div"> <div class="f_div"> </div> js: $("#findId").find('.f_div').css("color", "red");Copy the code

Network request

Finally, simple implementation of jQuery $. Ajax artifact.

ajax: function ({ url, dataType, success }) { var xhr = new XMLHttpRequest(); xhr.open(dataType, url); xhr.send(null); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { success(xhr.responseText); }; } }, $().ajax({ url: 'http://.... , dataType: 'GET', success: function (res) {alert(" interface returns data: "+ res); }})Copy the code

Such a simple version of jQuery and the implementation. After reading the simplified version, let’s analyze the advantages of JQ.

The advantage of the jQuery

JQuery, though, is crucial in dom handling. But he used to be hot, it is a lot of good. Let’s analyze:

  • Simple API

JQuery implements our long code in just a few letters, both on selectors and on network requests. The chain operation makes the page more concise.

  • Encapsulation of DOM operations

JQuery encapsulates a large number of common DOM operations, so that developers can be handy when writing DOM operations related programs. JQuery makes it easy to do all sorts of things that would otherwise be very complicated, making it possible for even a JavaScript novice to write great programs. JQuery has its own advantages in manipulating the DOM, but we need to operate it every time, unlike single-page architecture, which only updates the parts that need to be updated

  • Small and dirty

The introduction of jQuery itself is very small, with a minimum of around 15K, and the author’s encapsulation, which exposes the $value, does not contaminate the global variables.

  • Browser Compatibility

Single page compatibility, which supports IE10? If I remember correctly, the official statement is to support IE11 and above.

JQuery doesn’t have to worry about this. It supports IE 6.0+, FF 2+, Safari 2.0+ and Opera 9.0+

  • Rich plug-in support

In my eyes, jQuery so far has more ecological libraries than other frameworks, and it is introduced and used. In particular, some portal needs animation effects, game effects. His biosphere is historical.

  • Custom plug-in

$.fn. Extend = $.fn.

The framework suggested

Don’t go for frames when skills allow. The three frameworks are certainly good frameworks, but jQuery still has its place. For example, when I wrote portal, except for server-side rendering, I like to use simple jQuery to implement the rest. What are the disadvantages of jQuery, not just the portal? Dom operations cannot be reduced. But with our own requirements, no DOM manipulation, or very little, there are no defects. So you can still use jQuery on websites that don’t have much interaction.

The framework source code

The full example can be downloaded from Github: github.com/zhuangweizh…

(function (window) { var zQuery = function (selector) { return new zQuery.fn.init(selector); } zQuery.fn = { init: function (selector, myDocument) { this.dom = this.dom ? this.dom : []; this.myDocument = myDocument ? myDocument : document; const childNodes = this.myDocument.childNodes; var rs = null; if (typeof (selector) ! = 'undefined') {if (selector. Substr (0, 1) = = "#") {/ / id selector rs = this. MyDocument. GetElementById (selector. Slice (1)); this.dom[0] = rs; console.log("rs===" + rs.innerText + rs.innerHTML); } else if (selector. Substr (0, 1) = = ". ") {/ / style selector rs = this. MyDocument. GetElementsByClassName (selector. Slice (1)); for (var i = 0; i < rs.length; i++) { this.dom[i] = rs[i]; } } } return this; }, find: function (selector) { if (this.dom.length == 1) { this.init(selector, this.dom[0]); } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.init(selector, this.dom[i]); } } return this; }, html: function (value) { if (this.dom.length == 1) { this.dom[0].innerHTML = value; } else if (this.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style[attr] = value; } } }, css: function (attr, value) { if (this.dom.length == 1) { this.dom[0].style[attr] = value; } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style[attr] = value; } } }, show: function (attr, value) { if (this.dom.length == 1) { this.dom[0].style.display = 'block'; } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style.display = 'block'; } } }, hide: function (attr, value) { if (this.dom.length == 1) { this.dom[0].style.display = 'none'; } else if (this.dom.length > 1) { for (var i = 0; i < this.dom.length; i++) { this.dom[i].style.display = 'none'; Function ({url, dataType, success}) {var XHR = new XMLHttpRequest(); xhr.open(dataType, url); xhr.send(null); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { success(xhr.responseText); }; } }, } zQuery.fn.init.prototype = zQuery.fn; window.$ = zQuery; })(window);Copy the code

Blogging schedule

| | | blog theme sequence number link | | — – | — – | — — — — — — — — — — — – | | | 1 handwritten vue_mini source code parsing | juejin. Cn/post / 684790… | | 2 | handwritten react_mini source code parsing | juejin. Cn/post / 685457… | | 3 | handwritten webpack_mini source code parsing | juejin. Cn/post / 685457… | | | 4 handwritten jquery_mini source code parsing (that is, in this article) | juejin. Cn/post / 685457… | | | 5 handwritten vuex_mini source code parsing | juejin. Cn/post / 685705… Analytical | | | | 6 handwritten vue_router source is expected in August | | | 7 handwritten diff algorithm source code parsing | is expected in August | | | 8 written promise source code parsing | | August is expected to | | 9 handwritten native js source code parsing (manual to realize common API) | Is expected in August | | | handwritten react_redux 10, fiberd | backlog such as source code parsing, this plan out in this paper, first, arrange some difficulty | | | 11 handwritten koa2_mini | is expected in September, the front-end | priority

In addition to the source code during the article, may write one or two optimization, basic, etc. Interested in welcome to continue to pay attention.

The next article will write about the implementation of VUex.