浅析jquery原理,自己来封装个jQuery使用

加入QQ群:864680898,一起学习进步!点击群名可查看本人网站,有最新文章!

自己来封装个jQuery使用

相信很多人都是用过jquery,想我当初使用的时候也觉得非常好用,再也不用获取个dom就写那么长。而且我以前每次都会把document打错,编辑器还没得那些检查错误的插件,找个错都找不到。。。不说伤心事了。

封装一个函数的时候,我们可以有两条路来:

  • 1、我们已经知道调用的时候是什么样,那么来将实参传入,来决定函数怎么封装
  • 2、我们封装成形参多少个,各有什么作用,来实现什么功能

一、$获取dom

大家都使用过jquery的,那么也知道它获取dom就像 ( ′ . c o n t a i n e r ′ ) 一 般 , 直 接 使 用 选 择 器 。 可 见 ('.container') 一般,直接使用选择器。可见 (.container)使是个函数,将一个字符串传入,那么:

var $ = function (str) {

}

但是又发现它好像不只是传字符串,还具备以下特点:

  • 1、还可以传对象,就像 window、document、this 对象

  • 2、还能获取集合(如果一个类名有多个,jquery能返回一个类数组)

那么我们就需要对传入的内容进行分类了:

var $ = function (str) {
  var dom = choicObj(str);

  function choicObj(obj) {
    if (typeof obj == 'object') {
      return obj;
    } else {
      return document.querySelectorAll(obj).length > 1 ? document.querySelectorAll(obj) : document.querySelector(obj);
    }
  }
}

以上就能完成获取dom节点的功能,但是jquery远比这个复杂,因为它兼容到ie 6/7/8,里面有很多兼容的代码,像上面获取节点使用的 querySelector ,版本太低的浏览器是不支持的!

二、为获取到的dom添加事件的方法

我们常常使用jquery来添加点击事件,就像下面这样

$('.container').click(function(event){
  console.log('点击了一次')
})

出了点击,还有滑动,键盘按下,抬起,鼠标的一系列的事件,那么我们来添加事件

var $ = function (str) {
  var dom = choicObj(str);

  var events = ['click', 'scroll', 'keydown', 'keyup', 'mousedown', 'mousemove', 'mouseup', 'mousein', 'mouseout']
  events.forEach(function (v) {
    dom[v] = function (fn) {
      this.addEventListener(v, fn)
    }
  })

  function choicObj(obj) {
    if (typeof obj == 'object') {
      return obj;
    } else {
      return document.querySelectorAll(obj).length > 1 ? document.querySelectorAll(obj) : document.querySelector(obj);
    }
  }
  return dom;
}

现在能使用我们的$来获取节点并添加事件了,但是又出现另一个问题:

  • jquery添加了点击事件了之后还可以再添加其他事件及方法,例如
$('#box').click(function(e){
  console.log('我被点击了')
}).mousemove(function(e){
  console.log('鼠标在我身上移动')
})

然而我们的 $ 好像就不得行啊,这是怎么回事呢,因为我们在事件函数中没有返回对象

var $ = function (str) {
  var dom = choicObj(str);

  var events = ['click', 'scroll', 'keydown', 'keyup', 'mousedown', 'mousemove', 'mouseup', 'mousein', 'mouseout']
  events.forEach(function (v) {
    dom[v] = function (fn) {
      this.addEventListener(v, fn)

      return this;   // 返回jquery对象,才能下次继续调用它上面挂载的方法
    }
  })

  function choicObj(obj) {
    if (typeof obj == 'object') {
      return obj;
    } else {
      return document.querySelectorAll(obj).length > 1 ? document.querySelectorAll(obj) : document.querySelector(obj);
    }
  }
  return dom;
}

三、为jquery对象添加css方法,each······方法

用过jquery的小伙伴肯定用过css方法和each方法,就像下面这样:

$('.item').each(function(e,i){
  $(e).css({ height: 20, width: 20, background: '#33c9d4', margin: 10, paddingLeft: 10 }).click(function(event){
    console.log('点击到的是第'+ (i+1) +'个')
  })
})

我们来封装这个css和each函数,而且css函数大家都知道以下几点:

  • 1、当使用width,height这些单位的时候可以不写单位,直接使用数字,也可以用字符串带单位的形式
  • 2、增加样式后可直接在后面继续使用函数

那么我们先归纳一下一般什么属性的单位是px,那么我们给个默认值,例如:width,height···

var $ = function (str) {
  var dom = choicObj(str);

  var events = ['click', 'scroll', 'keydown', 'keyup', 'mousedown', 'mousemove', 'mouseup', 'mousein', 'mouseout']
  events.forEach(function (v) {
    dom[v] = function (fn) {
      this.addEventListener(v, fn)
      return this;
    }
  })

  dom.css = function (obj) {
    var pxPrototype = ['width', 'height', 'minWidth', 'minHeight', 'margin', 'padding', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft']
    for (var i in obj) {
      if (pxPrototype.includes(i) && typeof obj[i] == 'number') obj[i] = obj[i] + 'px'; // 为了方便使用了es6的includes
      this.style[i] = obj[i]
    }
    return this;
  }
  dom.each = function (fn) {
    this.forEach(fn)
    return dom;
  }

  function choicObj(obj) {
    if (typeof obj == 'object') {
      return obj;
    } else {
      return document.querySelectorAll(obj).length > 1 ? document.querySelectorAll(obj) : document.querySelector(obj);
    }
  }
  return dom;
}

接下来试一下我们的$变神奇了没,如果没有的话只能就用jquery了······

$('.item').each(function(e,i){
  $(e).css({ height: 20, width: 20, background: '#33c9d4', margin: 10, paddingLeft: 10 }).click(function(event){
    console.log('点击到的是第'+ (i+1) +'个')
  }).mousemove(function(){
    console.log('你在第' + (i+1) +'个上面移动')
  })
})

四、$能调用,它下面还有函数

就像ajax,在jquery中就是这样使用的:

$.ajax({ url: "test.html", context: document.body, success: function(){
    $(this).addClass("done");
}});

根据上面的结构我们便知道了ajax就是$下面的一个函数,传入的参数是一个对象,success便是一个成功后的回调,那么我们就开始来写个ajax吧

$.ajax = function(obj){
  var url = obj.url;
  var type = obj.type.toUpperCase() || 'GET';
  var data = obj.data || {};
  var headers = obj.headers || {};

  // GET方法的话,是将data里的参数拼接在url,POST方法的话是将data转成json发送过去
  if(type === 'GET'){
    url += '?';
    for(var i in data){
      url += (i + '=' + data[i]+ '&')
    }
    url = url.slice(0,url.length-1)
  }
  data = JSON.stringify(obj.data) || JSON.stringify({});

  var xhr = new XMLHttpRequest();
  xhr.open(type, url, true);
  // 带上请求头
  for(var i in headers){
    xhr.setRequestHeader(i, headers[i]);
  }
  xhr.send(data);
  xhr.onreadystatechange = function(){
    if(xhr.readyState===4 && xhr.status===200){
      try {
        var response = JSON.parse(xhr.responseText); // 后台一般也是返回一个json格式的数据,所以我们一般直接转了再用
        obj.success(response);
      } catch (err) {
        obj.error(err);
      }
    }
  }
}

然后我们来使用,就和jquery中一样的了

$.ajax({
  type: 'get',
  url: 'https://cnodejs.org/api/v1/topics',
  data:{ page: 2, limit: 8 },
  success: function(res){
    console.log(res)
  }, 
  error: function(err){
    console.log(err)
  }
})

使用post方式请求,就请求我学习socket的时候,一个发布公告的接口吧!其中请求头的token就是权限,一般由前端带上令牌去访问后台,后台会拦截没令牌的请求:

  • 这个token是有过期时间的,不可能随时提供出来,如果谁要练习post的使用可以加QQ群:864680898
$.ajax({
  type: 'post',
  url: 'http://mq.22family.com/api/message/notice',
  headers:{
    token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiYWRvcHRfbnVtIjowLCJwd2QiOiI1OTY4MTRmNTUwY2VkZmUxMzVjZWVlNGE3MzdlOWU0OSIsInBob25lIjoiIiwiZW1haWwiOiI0NzYxNjg3MTBAcXEuY29tIiwibmlja25hbWUiOiLmmbTlpKnnmoTpm6giLCJhdmF0YXIiOiJteVNLZXkvZmF2aWNvbi5wbmciLCJiaXJ0aCI6IiIsImRlcyI6IiIsInNvY2tldF9pZCI6IiIsImNyZWF0ZWQiOjE1NTEzMjMwODIsInVwZGF0ZWQiOjE1NTE5NTAxODgsImV4cGlyZSI6MTU1MjAzNjU4OH0.SjTrz34g3_1jMetFMGcwZcmsh4SELKmY4QZeWyg_6Nk'
  },
  data:{ content: 'hello world!' },
  success: function(res){
    console.log(res)
  }, 
  error: function(err){
    console.log(err)
  }
})

那么我们封装$.get()就十分方便了:

$.get = function(url,data,success,error){
  this.ajax({ type:'get', url, data, success, error })
}

然后来使用:

$.get('https://cnodejs.org/api/v1/topics', { page: 2, limit: 8 }, function(res){
  console.log(res)
})

五、完整的代码

最后附上这次jquery简单封装的全部代码

var $ = function (str) {
  var dom = choicObj(str);

  var events = ['click', 'scroll', 'keydown', 'keyup', 'mousedown', 'mousemove', 'mouseup', 'mousein', 'mouseout']
  events.forEach(function (v) {
    dom[v] = function (fn) {
      this.addEventListener(v, fn)
      return this;
    }
  })

  dom.css = function (obj) {
    var pxPrototype = ['width', 'height', 'minWidth', 'minHeight', 'margin', 'padding', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft']
    for (var i in obj) {
      if (pxPrototype.includes(i) && typeof obj[i] == 'number') obj[i] = obj[i] + 'px';
      this.style[i] = obj[i]
    }
    return this;
  }
  dom.each = function (fn) {
    this.forEach(fn)
    return this;
  }

  function choicObj(obj) {
    if (typeof obj == 'object') {
      return obj;
    } else {
      return document.querySelectorAll(obj).length > 1 ? document.querySelectorAll(obj) : document.querySelector(obj);
    }
  }
  return dom;
}

$.ajax = function(obj){
  var url = obj.url;
  var type = obj.type.toUpperCase() || 'GET';
  var data = obj.data || {};
  var headers = obj.headers || {};

  // GET方法的话,是将data里的参数拼接在url,POST方法的话是将data转成json发送过去
  if(type === 'GET'){
    url += '?';
    for(var i in data){
      url += (i + '=' + data[i]+ '&')
    }
    url = url.slice(0,url.length-1)
  }
  data = JSON.stringify(obj.data) || JSON.stringify({});

  var xhr = new XMLHttpRequest();
  xhr.open(type, url, true);
  // 带上请求头
  for(var i in headers){
    xhr.setRequestHeader(i, headers[i]);
  }
  xhr.send(data);
  xhr.onreadystatechange = function(){
    if(xhr.readyState===4 && xhr.status===200){
      try {
        var response = JSON.parse(xhr.responseText); // 后台一般也是返回一个json格式的数据,所以我们一般直接转了再用
        obj.success(response);
      } catch (err) {
        obj.error(err);
      }
    }
  }
}
$.get = function(url,data,success,error){
  this.ajax({ type:'get', url, data, success, error })
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值