jQuery设计思路(自己写一个jQuery)

140 阅读1分钟

结合阮一峰的jQuery设计思路,自己写一个简单的jQuery

代码放最后

jQuery的设计思路

1. 选取网页内元素

选取网页内某一元素,对其进行操作。

jQuery()获取对应的元素,但它不返回这些元素,

返回一个对象称为api, 这个对象可以直接操作对应的元素

window.$ = window.jQuery;
$(document) //选择整个文档对象  
  
$('#myId') //选择ID为myId的网页元素  
  
$('div.myClass') // 选择class为myClass的div元素  
  
$('input[name=first]') // 选择name属性等于first的input元素

2. 链式调用

每一步的jQuery操作,返回的都是一个当前所操作的jQuery对象,所以不同操作可以连在一起。

image.png

3. getter和setter模式

使用同一个函数,来完成取值(getter)和赋值(setter),即"取值器"与"赋值器"合一。到底是取值还是赋值,由函数的参数决定


$('h1').html(); //html()没有参数,表示取出h1的值
$('h1').html('Hello'); //html()有参数Hello,表示对h1进行赋值

4.重载

对于统一个属性传入不同的参数,运用重载可以的得到不同的作用效果。 image.png

元素的一些操作

image.png

image.png

image.png

遍历

image.png

5. 代码

window.$ = window.jQuery;
window.jQuery = function (selectorOrArrayOrTemplate) {
  let elements;
  //重载
  if (typeof selectorOrArrayOrTemplate === "string") {
    if (selectorOrArrayOrTemplate[0] === "<") {
      // 创建 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;
  }
  // 闭包 api 可以操作elements
  return {
    jquery: true,
    elements: elements,
    oldApi: selectorOrArrayOrTemplate.oldApi,

    get(index) {
      return elements[index];
    },
    //添加到某个节点
    appendTo(node) {
      if (node instanceof Element) {
        this.each((el) => node.appendChild(el)); // 遍历 elements,对每个 el 进行 node.appendChild 操作
      } else if (node.jquery === true) {
        this.each((el) => node.get(0).appendChild(el)); // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el))  操作
      }
    },
    //添加
    append(children) {
      if (children instanceof Element) {
        this.get(0).appendChild(children);
      } else if (children instanceof HTMLCollection) {
        for (let i = 0; i < children.length; i++) {
          this.get(0).appendChild(children[i]);
        }
      } else if (children.jquery === true) {
        children.each((node) => this.get(0).appendChild(node));
      }
    },
    //查找
    find(selector) {
      let array = [];
      for (let i = 0; i < elements.length; i++) {
        const elements2 = Array.from(elements[i].querySelectorAll(selector));
        array = array.concat(elements2);
      }
      array.oldApi = this; // this 就是 旧 api
      return jQuery(array);
    },
    // 遍历
    each(fn) {
      for (let i = 0; i < elements.length; i++) {
        fn.call(null, elements[i], i);
      }
      return this;
    },
    //获取父代
    parent() {
      const array = [];
      this.each((node) => {
        if (array.indexOf(node.parentNode) === -1) {
          array.push(node.parentNode);
        }
      });
      return jQuery(array);
    },
    //获取子代
    children() {
      const array = [];
      this.each((node) => {
        array.push(...node.children);
      });
      return jQuery(array);
    },
    //打印
    print() {
      console.log(elements);
    },
    //添加类
    addClass(className) {
      for (let i = 0; i < elements.length; i++) {
        const element = elements[i];
        element.classList.add(className);
      }
      return this;
    },
    end() {
      return this.oldApi; // this 就是新 api
    },
  };
};