我理解的jQuery

376 阅读2分钟

先导

  1. 什么是jQuery
  2. 自己实现jQuery的find和addClass方法
  3. jQuery链式调用的原理
  4. jQuery如果修改元素属性
  5. jQuery的设计模式

什么是jQuery

jQuery 是一个着重简化 DOM 操作,AJAX 调用和事件处理的 JavaScript 库。同时jQuery这个库已经从2006年第一个版本发布至今还有很多公司都在使用jQuery的库,将很长的DOM操作简单化,便于公司的使用,节省大量的时间.jQuery库包含以下功能:
1.HTML 元素选取
2.HTML 元素操作
3.CSS 操作
4.HTML 事件函数
5.JavaScript 特效和动画
6.HTML DOM 遍历和修改
7.AJAX
在本文中会提到以上的HTML元素选取以及HTML元素操作的实现原理,同时jQuery还提供了许多的设计模式在此文中也会提到,其中在jQuery中最重要的是链式调用是如何进行实现的,读者若感兴趣可以接下来看这篇文章

实现jQuery的find和addClass方法

若想实现jQuery需要先创建一个jQuery函数

window.jQuery = function () {
}

创建函数后需要传入selectorOrArray,判断是选择器还是子元素

window.jQuery = function (selectorOrArray) {
	// 在此处进行判断selectorOrArray是否为数组还是字符串,若为字符串的话则使用dom进行选择,若为数组的话直接赋值
    let elements;
    if(typeof selectorOrArray === 'string') {
    	elements = document.querySelectorAll('selectorOrArray')}
    else if(selectorOrArray instanceof Array){
     	elements = selectorOrArray   		
    }
}

接下来我们要实现find方法了

window.jQuery = function (selectorOrArray) {
	// 在此处进行判断selectorOrArray是否为数组还是字符串,若为字符串的话则使用dom进行选择,若为数组的话直接赋值
    let elements;
    if(typeof selectorOrArray === 'string') {
    	elements = document.querySelectorAll('selectorOrArray')}
    else if(selectorOrArray instanceof Array){
     	elements = selectorOrArray   		
    }
    // 首先要返回一个对象在操作下一步时才能使用
    return {
    		find(selecotr) {
            	let array = [];
                // 通过遍历elements每个元素然后将通过querySelectorAll选择到相应的selector添加到array数组中
                for(let i=0;i<elements.length;i++) {
                	array = array.concat(Array.from(elements[i].querySelectorAll(selector)))
            }
    	}
}

接下来我们要实现addClass方法了

window.jQuery = function (selectorOrArray) {
	// 在此处进行判断selectorOrArray是否为数组还是字符串,若为字符串的话则使用dom进行选择,若为数组的话直接赋值
    let elements;
    if(typeof selectorOrArray === 'string') {
    	elements = document.querySelectorAll('selectorOrArray')}
    else if(selectorOrArray instanceof Array){
     	elements = selectorOrArray   		
    }
    // 首先要返回一个对象在操作下一步时才能使用
    return {
    		find(selecotr) {
            	let array = [];
                // 通过遍历elements每个元素然后将通过querySelectorAll选择到相应的selector添加到array数组中
                for(let i=0;i<elements.length;i++) {
                	array = array.concat(Array.from(elements[i].querySelectorAll(selector)))
            }
    	},
        // 添加class的方法比较简单,只需获取每个元素的class列表然后通过add方法加进去即可
        	addClass(className){ 
            	for(let i=0;i<elements.length;i++){
                	elements[i].classList.add(className)}
}

以上的两种方法仅实现了find和addclass,并没有链式调用,接下来我们开始加入链式调用了

jQuery链式调用的原理

window.jQuery = function (selectorOrArray) {
	// 在此处进行判断selectorOrArray是否为数组还是字符串,若为字符串的话则使用dom进行选择,若为数组的话直接赋值
    let elements;
    if(typeof selectorOrArray === 'string') {
    	elements = document.querySelectorAll('selectorOrArray')}
    else if(selectorOrArray instanceof Array){
     	elements = selectorOrArray   		
    }
    // 首先要返回一个对象在操作下一步时才能使用
    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)))
                  }
                  // 在此处创建一个新的jQuery对象,用来返回,否则若直接返回this,则会改变了elements
                  // 此处的思路,在array加上oldApi对象保存上一次的this,然后在this中创建一个oldApi保存更改前的this指向以便于end获取,通过end可以直接获取
                  array.oldApi = this
                  return jQuery(array)
                },
}

我们将会在find函数内返回出一个jQuery(array),将在addClass内返回一个this(this指向的是jQuery返回的对象),链式调用的原理其实返回一个可继续操作的选择器,由于addClass并没有改变当前的选择器的位置所以直接返回即可,但是find后要改变当前选择器的位置,所有利用的是jQuery(array)

jQuery如果修改元素属性

window.jQuery = function(selectorOrArray){
  let elements;
  if(typeof selectorOrArray ==='string') {
    elements = document.querySelectorAll(selectorOrArray)
  } else if(selectorOrArray instanceof Array) {
    elements = selectorOrArray
  }
  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)
    },
    style(name,value) {
      if(arguments.length === 2) {
        for(let i=0;i<elements.length;i++) {
          elements[i].style[name] = value
        }
      }else if(arguments.length === 1) {
        for(let i=0;i<elements.length;i++) {
          console.log(elements[i].style[name]);
        }
      }
      return this
    }
  }
}

在style中可以直接看到代码,有两个参数,然后运用了上一篇DOM文章提到的重载技巧,判断参数的长度,然后同样如果还想运用链式操作需要返回一个this

jQuery的设计模式

  1. 不用new的构造函数,这个模式没有专门的名字
  2. $支持多种参数(重载)
  3. 用闭包隐藏了细节
  4. $.text()既可读也可写,类似于getter/setter
  5. .fn.fn是.prototype的别名
  6. jQuery针对不同浏览器使用不同的代码(适配器)

总结

虽然jQuery已经存在了很久,但是里面的很多内容都是我们值得学习的,比如运用了闭包,防止变量的泄露,更改prototype的名称,在本篇文章中仅列举了部分的jQuery的实现方法,但是本质上的思路也是差不多的,运动到的就是遍历的形式,如果大家有兴趣也可以去参考一下jQuery的源码进行学习.
记得持续学习,不断跟进!加油!