jQuery封装DOM

前言

在自己封装了一个简单的DOM库之后,发现封装一个库还是不难的。

我所理解的jQuery

其实很简单,我们操作某个对象,不返回这个对象,返回操作这个对象的对象
jQuery 示例:

window.jQuery = function (selectorOrArrayOrTemplate) {
  let elements;
  if (typeof selectorOrArrayOrTemplate === "string") {
    // 传进来的是选择器
    elements = document.querySelectorAll(selectorOrArrayOrTemplate);
  } else if (selectorOrArrayOrTemplate instanceof Array) {
    // 传进来的是数组
    elements = selectorOrArrayOrTemplate;
  }

  //elements就是要操作的元素或者节点

  let api = {
    // 下面这些函数可以操作 elements
    find(selector) {
      let array = [];
      for (let i = 0; i < elements.length; i++) {
        const elements2 = Array.from(elements[i].querySelectorAll(selector));
        array.push(...elements2);
      }
      array.oldApi = this; // this 就是 旧 api
      return jQuery(array);
      //目的是返回新的api,新的elements值
    },
    appendTo(selector) {},
    addClass(className) {},
    end(className) {},
  };

  return api;
};

可以看到,最后返回的是api,而这个api又包含了属性和方法。
jQuery就是把该有的功能像这样,写进这个库,基本思想不变。

链式调用

所谓链式调用,就是let api = jquery(".text").find(".text1").addClass("red");
为什么可以链式调用,就是因为返回的是本身。

window.jQuery = function (selectorOrArrayOrTemplate) {
  let elements;
  if (typeof selectorOrArrayOrTemplate === 'string') {
    if (selectorOrArrayOrTemplate[0] === "<") {
      //创建div
      elements = [createElement(selectorOrArrayOrTemplate)]
    } else {
      //查找div
      elements = 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,
    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 = element[i];
        element.classList.add(className);
      }
      return this;
    },
    oldApi: selectorOrArrayOrTemplate.oldApi,
    end() {
      return this.oldApi;//this就i是新api
    },
  }
}

window.$ = window.jQuery

贴出来大段代码。
代码很精简,但是理解起来很费功夫。
首先:接受的参数window.jQuery = function (selectorOrArrayOrTemplate)参数的种类有几种,根据参数的不同,返回不同操作参数的对象。
this:代码中多次看到return this参见最开头的代码,this就是前面代码的api,api包含操作这个属性的所有方法。
end方法:这一大段代码的最后可以看到有一个方法是end
return this.oldApi,this代表现在的所有(整个对象)的东西,this.oldApi是操作oldApi的对象
protoType:每一个对象都可以有这些属性,所以会浪费很多内存,jQuery也想到了这一点,把所有共有属性放到protoType,这样就节约了空间。
总结一下
代码简单,理解起来还是不容易的,要自己写出来就更困难了,多练习才能熟能生巧

贴上我的GitHub仓库链接自己封装的jQuery

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值