preface

  • In this section, the DOM code encapsulated in the previous section is repackaged in jQuery style
  • JQuery is very simple

Repackage in jquery-style

You’re probably saying to yourself a lot in this class: Why didn’t I think of that? !

The preparatory work

The preparation of each section is similar, and you can use it slowly

Create the project directory dom-2 > SRC > index.html, main.js, jquery.js

index.html

<! DOCTYPEhtml>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Writing jQuery</title>
</head>
<body>hello<script src="jquery.js"></script>
  <script src="main.js"></script>
</body>
</html>
Copy the code

jquery.js

// Declare window.jQuery to be a function (? ! Never mind why it's a function.)
window.jQuery = function () {
  console.log(` I'm jQuery `)}Copy the code

main.js

jQuery() // window. JQuery () // output: I'm jQuery
Copy the code

Enabling local Services

yarn global add parcel
parcel src/index.html
Copy the code

Chain style ❤️

Take a look at what code we are going to implement 👇

Also called jQuery style

  • Window.jquery () is the global function we provide

Special function jQuery

  • JQuery (selector)Used to get the corresponding element
  • But it does not return these elements
  • Instead, it returns an object, called the object constructed by jQuery (the API in the handwritten DOM from the previous section)
  • This object can manipulate the corresponding element
  • Don’t understand? Straight to the code!

Code ⭕ ️

index.html

<body>
  <div class="test">Hello 1</div>
  <div class="test">Hello 2</div>
  <div class="test">Hello 3</div>
  <script src="jquery.js"></script>
  <script src="main.js"></script>
</body>
Copy the code

jquery.js

// Declare window.jQuery to be a function (? !). (Never mind why it's a function)
window.jQuery = function (selector) {
  const elements = document.querySelectorAll(selector)  // Get all the elements of the selector (get an array)
  // return elements
  // General operation: just return the element found through the selector.
  // But jQuery does something unusual: instead of returning an element, jQuery returns an API that can manipulate that element
  / / is as follows:
  // The API can operate elements
  // The API is an object that contains various functions that operate on elements.
  // For example, addClass is the function that adds the class name to elements
  const api = {
    // Access variables outside the function. This is called a closure.
    addClass(className) {
      // Elements are variables outside the function addClass
      for (let i = 0; i < elements.length; i++) { // Iterate over all the obtained elements and add the class name
        elements[i].classList.add(className)
      }
      // return null
      return api // the method still returns the API, which in turn contains many methods that can be called through the return value. addClass forms a chain 📌
      // This is the chain style 📌}}return api
}
Copy the code

main.js

const api = jQuery(".test") // The element is retrieved from the selector, but is not returned
// Instead, it returns an API object containing a number of methods that can control the element
// console.log(api.addClass)
// Iterate over all the elements and add the.red class name
api.addClass("red").addClass('blue')
// The return value of the api.addClass method is still API, so the call can continue through the return value
Copy the code

1️ one

The following change in return must be understood

Return SAO operation 1️ one

Use this instead of API

window.jQuery = function (selector) {
  const elements = document.querySelectorAll(selector)  // Get all the elements of the selector (get an array)
  const api = {
    addClass(className) {
      for (let i = 0; i < elements.length; i++) { 
        elements[i].classList.add(className)
      }
      // return api
      return this  
      /* * This is the same as the previous object * obj.fn(p1); ↓ * obj.fn. Call (obj, p1); AddClass ("red") => This is the API when obj * is called. AddClass ("red") => Similarly, in addClass this is the API. Return this *; return this *; return this *; return this *; return this *; return this *}}return api
}
Copy the code

Return SAO operation 2️ one

Remove the API from jQuery completely

  • Since we created the API object and then returned the API object, can’t we just return the object and omit the ASSIGNMENT part of the API?
  • Would it not be “redundant”
window.jQuery = function (selector) {
  const elements = document.querySelectorAll(selector) 
  const api = {  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    addClass(className) {
      for (let i = 0; i < elements.length; i++) {
        elements[i].classList.add(className)
        
      }
      return this}}return api    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}

// omit the API assignment link 👇
window.jQuery = function (selector) {
  const elements = document.querySelectorAll(selector)  // Get all the elements of the selector (get an array)
  // const api = {
  return {
    addClass(className) {
      for (let i = 0; i < elements.length; i++) {
        elements[i].classList.add(className)
        
      }
      return this}}// return api 
}
Copy the code

The core idea of jQuery

The first core point: closures

  1. A jQuery function that receives a CSS selector
  2. Using the selector, we get the element Elements (but don’t return it), which returns an object
  3. The object returned contains many functions. These functions can operate on elements

Principle:

  • Use “closures” to maintain elements
    • Because the addClass function is accessing Elements. Accessed variables are not simply recycled by the browser
    • This is one of the core ideas of jQuery

Second core point: chain operation

  • AddClass, you can guess: when the user calls addClass, it must passJQuery (selector)Get the API to call
  • That’s why I boldly return this.
  • The addClass function wants to return whatever comes before the dotapi.addClass("red")
  • So basically, the API goes from the front of addClass to the back of addClass, so you can call addClass👇 API. The addClass (" red ") 👇. AddClass (" blue ")
  • This is called chain operation.

JQuery code variant 2️ one

Main.js simplifies calls

Get rid of the variable x

const x = jQuery(".test")  // Declare x, then use it directly. That assignment, that's redundant
x.addClass("red").addClass('blue').addClass('green')

// 👇 is eventually written as 👇
jQuery(".test").addClass("red").addClass('blue').addClass('green')
Copy the code

A small summary

  • Advanced front-end code eliminates all intermediate processes
  • Cut out all the things that don’t matter
  • The result is the most concise code with the least information
  • Although the code is extremely concise and elegant, it is simply incomprehensible to learners. (Note that “source code” is really not suitable for learners)

Is jQuery a constructor?

At this point you may have this question 👆

Constructors: ① before the new, ② to construct the object

  • Combining these two characteristics, you can think of jQuery as a constructor or not

is

  • Because the jQuery function does construct an object

not

  • You don’t need to write new jQuery() to construct an object
  • All of the previous constructors have to combine new

conclusion

  • JQuery is a constructor that doesn’t need to add new
  • JQuery is not a constructor in the normal (strict) sense
  • This is because jQuery uses a few tricks (not necessary at this point, but confusing for beginners)

The term

Oral agreement 👄

The jQuery function returns an object called an object constructed by jQuery (the API in the original code).

Oral agreement:

  • When we talk about jQuery objects, we will refer to objects constructed by jQuery functions.
  • I’m not saying “jQuery this object”
  • Make sure you remember

Other examples

  • Object is a function
  • Object, which represents the Object constructed by the Object constructor (not Object itself is an Object)
  • Array is a function
  • Array object/Array object, representing the object constructed by Array (not Array itself is an object)
  • Function is a Function
  • Function object/Function object, representing the object constructed by Function (not Function itself is an object)

More versatile packages ⭕️

The chain style

check

jQuery('#xxx')                The return value is not an element, but an API object
jQuery('#xxx').find('.red')   // Look for the.red element in # XXX
jQuery('#xxx').parent()       // Get dad
jQuery('#xxx').children()     // Get the son
jQuery('#xxx').siblings()     // Get brothers
jQuery('#xxx').index()        // Get the ranking number (starting from 0)
jQuery('#xxx').next()         // Get the brother
jQuery('#xxx').prev()         // Get the elder brother
jQuery('.red').each(fn)       // Iterate over and perform fn on each element
Copy the code

code

window.jQuery = function (selectorOrArray) {
  /* * elements always represents a collection of the selector's target elements * */
  let elements
  if (typeof selectorOrArray === "string") {  / / overloaded
    elements = document.querySelectorAll(selectorOrArray)
  } else if (selectorOrArray instanceof Array) {
    elements = selectorOrArray
  }
  // 👇 returns the object API constructed by the jQuery function.
  return {
    addClass(className) {
      for (let i = 0; i < elements.length; i++) {
        elements[i].classList.add(className)
      }
      return this
    },
    find(selector) {
      let array = []
      for (let i = 0; i < elements.length; i++) {
        array = array.concat(Array.from(elements[i].querySelectorAll(selector)))
      }
      return jQuery(array)  // <<<<<<<< focus on the following statement:
    },
    oldApi: selectorOrArray.oldApi,
    end() {
      return this.oldApi
    },
    each(fn) {
      for (let i = 0; i < elements.length; i++) {
        fn.call(null, elements[i], i, elements)  // Iterate over each item, executing some method on each item
      }
      return this
    },
    print() {
      console.log(elements)
      return this
    },
		parent() {
      const array = []
      this.each(node= > {
        if (array.indexOf(node.parentNode) === -1) { / / to heavy
          array.push(node.parentNode)
        }
      })
      array.oldApi = this
      return jQuery(array)
    },
    children() {
      const array = []
      this.each(node= > {
        if(node.children) { array.push(... node.children)// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        }
      })
      array.oldApi = this
      return jQuery(array)
    },
    / * * * * * * * * * * * * * * * * * * * * * the following is not mentioned in front of the * * * * * * * * * * * * * * * * * * * * * /
    /* siblings() index() next() prev() */}}Copy the code

practice

/* 
      
1
2
3
*/
window.jQuery = function(selectorOrArray){ let elements if(typeof selectorOrArray === 'string'){ elements = document.querySelectorAll(selectorOrArray) }else if(selectorOrArray instanceof Array){ elements = selectorOrArray } return { addClass(className){ this.each(n= >n.classList.add(className)) }, find(selector){ let array = [] this.each(n= >{ array.push(... n.querySelectorAll(selector)) })return jQuery(array) }, each(fn){ for(let i=0; i<elements.length; i++){ fn.call(null, elements[i], i) } } } } window$=window.jQuery $('#test').find('.child').addClass('red') // Please make sure this sentence is executed successfully Copy the code

increase

Just a quick thought

code

// A quick review of dom node creation 👇 (two ways)
const div = document.createElement('div')  // ① Pass in the label name
template.innerHTML = '<div></div>'  / / (2) to HTML structure, and finally returned to the template. The content. firstChild
Copy the code
window$=window.jQuery = function(selectorOrArrayOrTemplate) {
  let elements;
  if (typeof selectorOrArrayOrTemplate === "string") {
    if (selectorOrArrayOrTemplate[0= = ="<") {
      / / create a div
      elements = [createElement(selectorOrArrayOrTemplate)];
    } else {
      / / div
      elements = document.querySelectorAll(selectorOrArrayOrTemplate); }}else if (selectorOrArrayOrTemplate instanceof Array) {
    elements = selectorOrArrayOrTemplate;
  }

  function createElement(string) {
    const container = document.createElement("template");
    container.innerHTML = string.trim();
    return container.content.firstChild;
  }
	
  // Return the API created by jQuery
  return{
    appendTo(node) {
      if (node instanceof Element) {
        this.each(el= > node.appendChild(el));
      } else if (node.jquery === true) {
        this.each(el= > node.get(0).appendChild(el)); }},// ...}}// Create a div and insert it into the body
$('<div><span>1</span></div>').appendTo(document.body) 
Copy the code

delete

The same logic as the DOM implementation

$div.remove() 
$div.empty()  
Copy the code

change

The same logic as the DOM implementation

$div.text(?) // If you pass an argument, you write it. If you don't pass an argument, you read it.
$div.html(?) // If you pass an argument, you write it. If you don't pass an argument, you read it.
$div.attr('title',?)// Read and write properties
$div.css({color: 'red'})  // write style // note that the method name is CSS
$div.addClass('blue') 
$div.on('click', fn) 
$div.off('click', fn)Copy the code

Pay attention to

  • Most of the time, $div corresponds to multiple div elements
  • Be sure to default $div to an array and iterate over it (every operation)

window.$ = window.jQuery

jQuery('#test') // Write it this way every time you use it
Copy the code

What? You think jQuery is too long

  • You are right
  • JQuery is a hard word to spell (and case sensitive)
  • How can I make jQuery shorter?
  • Bash Alias Remember bash Alias, just add an alias
// Must be added at the end of the code
window.jQuery = function (selectorOrArray){... }window$=window.jQuery
Copy the code
  • After that, using $anywhere is equivalent to using jQuery
  • Also can save trouble 👇 again
window$=window.jQuery = function (selectorOrArray){... }// Write on one line from right to left
JQuery = function(){}
// Then assign the result of window.jQuery to window.$
Copy the code
  • This is the way many advanced programmers write it