加入QQ群:864680898,一起学习进步!点击群名可查看本人网站,有最新文章!
相信很多人都是用过jquery,想我当初使用的时候也觉得非常好用,再也不用获取个dom就写那么长。而且我以前每次都会把document打错,编辑器还没得那些检查错误的插件,找个错都找不到。。。不说伤心事了。
封装一个函数的时候,我们可以有两条路来:
大家都使用过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 ,版本太低的浏览器是不支持的!
我们常常使用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;
}
现在能使用我们的$来获取节点并添加事件了,但是又出现另一个问题:
$('#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方法,就像下面这样:
$('.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函数大家都知道以下几点:
那么我们先归纳一下一般什么属性的单位是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就是权限,一般由前端带上令牌去访问后台,后台会拦截没令牌的请求:
$.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 })
}