回到正题,如jQuery般易用的api风格?那到底是什么样的风格呢?个人觉得比较重要的有两点,一是对dom操作的链式调用,并且都呈队列状态,不仅仅使代码的可读语义变得通俗易懂,而且省去了对同一dom元素的多个链式操作时的回调中嵌回调的方式,这是很重要的一点。
二是对元素的批量操作,这是建立在它强大的选择器上的。jq选择器很强大,这是人所众知的,就不多说了。而且肯定也不是一两天就能实现的了的,所以下面就对我所说的这两点谈谈我的看法。
基于它强大的选择器,jquery所有的dom操作都依赖于根据它选择器取到的一个数组,很多人喜欢把这叫做jq对象。那咱们暂时也先这样叫吧。然后所有的dom操作都是依赖于这个jq对象中每一个元素并发批量执行的。具体到每一个dom操作,大部分的都是呈链式回调的状态,也就是说在这个方法链里面,直接根据方法调用在链中的先后顺序就能知道他们执行的顺序。这种方法链并且串行的形式是它的一大特色。
以至于很多人喜欢用jquery,基本就看中它两点,选择器确实很强大,链式调用确实很方便很易用,代码逻辑瞬间变得简单。正因为他把很多的代码逻辑都放到自己内部去处理了,留给编码者考虑的问题就少了很多,所以一方面你觉得好用的同时,也就失去了一次锻炼编码逻辑的机会。因此我不建议初学者直接学习使用jquery或者其他的框架,因为他们会让你对js的理解越来越少。我的观点是所有的框架或者库都是拿来使用的,拿来提高开发效率和管理便利度的,而不是拿来学习的。(当然,研究源码的除外)。
那么,既然觉得jquery的api风格好用,那我们何尝不尝试一下构建这种类似的api风格呢?(声明:以下尝试都仅仅是提供一种思路,代码并不完善...)
var get = function (ids) {
var d = document, a = -1;
this.elements = [];
if (typeof ids != 'string' && !!ids.length) {
for (var i=0; i
o = typeof id == 'string' ? d.getElementById(id) : id;
this.elements.push(o);
}
} else {
while (typeof arguments[ a] == 'string') {
this.elements.push(d.getElementById(arguments[a]));
}
}
}
然后为它扩展一些操作dom的方法
get.prototype = {
each : function () {},
animate : function () {}
}
当然,这种方式和jQuery看起来不太一样,但能理解就行,jquery可能是这个样子:
jQuery = window.jQuery = window.$ = function( selector, context ) {
return new jQuery.fn.init( selector, context );
}
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {}
}
接下来对获取的队列进行批量操作,不可避免的就需要一个each的遍历方法。
each : function (fn) {
for (var i=0; i
}
return this;
},
each为get.prototype扩展出的方法,提供一个参数function,并且遍历dom列表,把function绑定到每一个元素上。然后让它返回get.prototype,因为prototype本身具有类似于“超类”的性质,所以凡是返回给prototype对象的方法都能继续调用prototype扩展出来到方法。
为了使这个尝试更有意义一点,接下来来做一个animate的函数吧。这个函数是jquery对dom操作很常用的一个方法,有了它,大部分的动画都变得那么简单和容易了。下面会是一个简单的实现:
animate: function (config) {
if (!this.animQueue) this.animQueue = HR._animQueue = [];
var a = 0, time, tween, ease, callback;
while (arguments[ a]) {
if (typeof arguments[a] == 'number') time = arguments[a];
if (typeof arguments[a] == 'string') {
if (/^ease*/.test(arguments[a])) ease = arguments[a];
else tween = arguments[a];
}
if (HR.isFunction(arguments[a])) callback = arguments[a];
}
this.animQueue.push({
config: config,
time: time,
tween: tween,
ease: ease,
callback: callback
});
if (this.animQueue.length == 1) this.execute(this.animQueue);
return this;
},
光看这一段可能看不出什么端倪,是的,因为要像jquery一样做成串行的方法链,就需要一个临时队列来操作,要不然即使方法链形成了,但这些方法都是并行的,达不到我们想要的效果。所以上面一段代码主要是处理animate推入队列的一个逻辑,然后对参数arguments做了一些判断,以便在写参数的时候能更加随意,除了第一个参数和最后一个callback外,其余参数不用考虑位置和是否必填,以增强易用性。
核心的变换函数在execute上,
execute : function (queue) {
var _this = this, m = 0, n = 0,
_anim = function (el, key, from, to, at, tw, ease, cb) {
var isOP = (key == 'opacity' && !HR.support.opacity), _key = key;
if (isOP) {to = to*100; _key = 'filter'}
var s = new Date,
d = at,
b = parseFloat(from) || 0,
c = to-b;
(function () {
var t = new Date - s;
if (t >= d) {
n ;
t = d;
el.style[_key] = (isOP ? 'alpha(opacity=' : '') Tween.Linear(t, b, c, d) (key != 'opacity' ? 'px' : '') (isOP ? ')' : '');
!!cb && cb.apply(el);
if (m == n && _this.animQueue.length > 1) {
_this.animQueue.shift();
_this.execute(_this.animQueue);
}
return;
}
el.style[_key] = (isOP ? 'alpha(opacity=' : '') Tween[tw][ease](t, b, c, d) (key != 'opacity' ? 'px' : '') (isOP ? ')' : '');
if (!HR.timers[el.id]) HR.timers[el.id] = [];
HR.timers[el.id].push(setTimeout(arguments.callee, 16));
})();
},
_q = this.animQueue[0];
return this.each(function (el) {
for (var k in _q.config) {
m ;
_anim(el,
k,
k == 'opacity' && !HR.support.opacity ? HR.getStyle('filter', el) == '' ? 100 : parseInt(HR.getStyle('filter', el).match(/d{1,3}/g)[0]) : HR.getStyle(k, el),
_q.config[k],
typeof _q.time == 'number' ? _q.time : 1000,
typeof _q.tween == 'string' && !/^ease*/.test(_q.tween) ? _q.tween : 'Quart',
typeof _q.ease == 'string' && /^ease*/.test(_q.ease) ? _q.ease : 'easeOut',
_q.callback)
}
});
}
这一段看起来就要复杂一些了,最基本的变化还是在_anim这个私有函数上。其余的代码基本在做一些批量的操作,和透明度变化兼容性,以及当前变换是否执行完毕的功能。结合这两段,基本就实现了jquery的animate的效果了。属于一个简化版本。
当然,还不能忘了很重要的一点,就是既然可以变换,那就必须有个stop的方法让这个变换可控,要不然这个代码的可用性会大打折扣,参考以下代码:
stop : function (clearQueue) {
if (clearQueue) HR._animQueue.length = 0;
this.each(function (el) {
if (!!HR.timers[el.id])
for (var i=0; i
return this;
},
针对不同的dom元素id设置专门的临时计时器存贮,HR.timers[el.id],然后遍历当前dom列表,把对应的计时器clear掉。参数clearQueue作为可选参数,用来控制是否清掉后续等待执行的animate。
为了让这个方法更加好玩一点,我加了几种额外的缓动方式,jquery只有一种swing,然后所有的缓动算法放置在Tween对象中以供使用。下面是我做测试的源码,(如有纰漏,各位见谅)
/* =========== animate js ============ */
/* @author:hongru.chen */
/* =================================== */
if (typeof HR == 'undefined' || !HR)
HR = {
extend : function (destination, source, override) {
if (override === #ff0000) override = true;
for (var property in source) {
if (override || !(property in destination)) {
destination[property] = source[property];
}
}
return destination;
}
};
(function () {
var Tween = { // 以下算子的参数分别表示: t:运行时间,b:开始量,c:总变化量,d:总时间
Linear: function(t,b,c,d){ return c*t/d b; },
Quad: {
easeIn: function(t,b,c,d){
return c*(t/=d)*t b;
},
easeOut: function(t,b,c,d){
return -c *(t/=d)*(t-2) b;
},
easeInOut: function(t,b,c,d){
if ((t/=d/2) return -c/2 * ((--t)*(t-2) - 1) b;
}
},
Cubic: {
easeIn: function(t,b,c,d){
return c*(t/=d)*t*t b;
},
easeOut: function(t,b,c,d){
return c*((t=t/d-1)*t*t 1) b;
},
easeInOut: function(t,b,c,d){
if ((t/=d/2) return c/2*((t-=2)*t*t 2) b;
}
},
Quart: {
easeIn: function(t,b,c,d){
return c*(t/=d)*t*t*t b;
},
easeOut: function(t,b,c,d){
return -c * ((t=t/d-1)*t*t*t - 1) b;
},
easeInOut: function(t,b,c,d){
if ((t/=d/2) return -c/2 * ((t-=2)*t*t*t - 2) b;
}
},
Quint: {
easeIn: function(t,b,c,d){
return c*(t/=d)*t*t*t*t b;
},
easeOut: function(t,b,c,d){
return c*((t=t/d-1)*t*t*t*t 1) b;
},
easeInOut: function(t,b,c,d){
if ((t/=d/2) return c/2*((t-=2)*t*t*t*t 2) b;
}
},
Sine: {
easeIn: function(t,b,c,d){
return -c * Math.cos(t/d * (Math.PI/2)) c b;
},
easeOut: function(t,b,c,d){
return c * Math.sin(t/d * (Math.PI/2)) b;
},
easeInOut: function(t,b,c,d){
return -c/2 * (Math.cos(Math.PI*t/d) - 1) b;
}
},
Expo: {
easeIn: function(t,b,c,d){
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) b;
},
easeOut: function(t,b,c,d){
return (t==d) ? b c : c * (-Math.pow(2, -10 * t/d) 1) b;
},
easeInOut: function(t,b,c,d){
if (t==0) return b;
if (t==d) return b c;
if ((t/=d/2) return c/2 * (-Math.pow(2, -10 * --t) 2) b;
}
},
Circ: {
easeIn: function(t,b,c,d){
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) b;
},
easeOut: function(t,b,c,d){
return c * Math.sqrt(1 - (t=t/d-1)*t) b;
},
easeInOut: function(t,b,c,d){
if ((t/=d/2) return c/2 * (Math.sqrt(1 - (t-=2)*t) 1) b;
}
},
Elastic: {
easeIn: function(t,b,c,d,a,p){
if (t==0) return b; if ((t/=d)==1) return b c; if (!p) p=d*.3;
if (!a || a else var s = p/(2*Math.PI) * Math.asin (c/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) b;
},
easeOut: function(t,b,c,d,a,p){
if (t==0) return b; if ((t/=d)==1) return b c; if (!p) p=d*.3;
if (!a || a else var s = p/(2*Math.PI) * Math.asin (c/a);
return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) c b);
},
easeInOut: function(t,b,c,d,a,p){
if (t==0) return b; if ((t/=d/2)==2) return b c; if (!p) p=d*(.3*1.5);
if (!a || a else var s = p/(2*Math.PI) * Math.asin (c/a);
if (t return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 c b;
}
},
Back: {
easeIn: function(t,b,c,d,s){
if (s == undefined) s = 1.70158;
return c*(t/=d)*t*((s 1)*t - s) b;
},
easeOut: function(t,b,c,d,s){
if (s == undefined) s = 1.70158;
return c*((t=t/d-1)*t*((s 1)*t s) 1) b;
},
easeInOut: function(t,b,c,d,s){
if (s == undefined) s = 1.70158;
if ((t/=d/2) return c/2*((t-=2)*t*(((s*=(1.525)) 1)*t s) 2) b;
}
},
Bounce: {
easeIn: function(t,b,c,d){
return c - Tween.Bounce.easeOut(d-t, 0, c, d) b;
},
easeOut: function(t,b,c,d){
if ((t/=d) return c*(7.5625*t*t) b;
} else if (t return c*(7.5625*(t-=(1.5/2.75))*t .75) b;
} else if (t return c*(7.5625*(t-=(2.25/2.75))*t .9375) b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t .984375) b;
}
},
easeInOut: function(t,b,c,d){
if (t 否则返回 Tween.Bounce.easeOut(t*2-d, 0, c, d) * .5 c*.5 b;
}
}
}
var get = function (ids) {
var d = document, a = -1;
this.elements = [];
if (typeof ids != 'string' && !!ids.length) {
for (var i=0; i
o = typeof id == '字符串' ? d.getElementById(id) : id;
this.elements.push(o);
}
} else {
while (typeof argument[ a] == 'string') {
this.elements.push(d.getElementById(arguments[a]));
}
}
}
get.prototype = {
each : function (fn) {
for (var i=0; i
}
返回这个;
},
setStyle : function (p, v) {
this.each(function (el) {
el.style[p] = v;
});
返回这个;
},
show : function () {
var _this = this;
this.each(function (el) {
_this.setStyle('display', 'block');
})
返回这个;
},
隐藏 : function () {
var _this = this;
this.each(function (el) {
_this.setStyle('display', 'none');
})
返回这个;
},
animate: function (config) {
if (!this.animQueue) this.animQueue = HR._animQueue = [];
var a = 0,时间,补间,缓动,回调;
while (arguments[a]) {
if (typeof argument[a] == 'number') time = argument[a];
if (typeof argument[a] == 'string') {
if (/^ease*/.test(arguments[a])) ease = argument[a];
else tween = 参数[a];
}
if (HR.isFunction(arguments[a])) 回调 = argument[a];
}
this.animQueue.push({
config: 配置,
时间: 时间,
补间: 补间,
ease: 轻松,
回调:回调
});
if (this.animQueue.length == 1) this.execute(this.animQueue);
返回此;
},
stop : function (clearQueue) {
if (clearQueue) HR._animQueue.length = 0;
this.each(function (el) {
if (!!HR.timers[el.id])
for (var i=0; i
返回这个;
},
execute : function (queue) {
var _this = this, m = 0, n = 0,
_anim = function (el, key, from, to, at , tw, ease, cb) {
var isOP = (key == 'opacity' && !HR.support.opacity), _key = key;
if (isOP) {to = to*100; _key = 'filter'}
var s = new Date,
d = at,
b = parseFloat(from) || 0,
c = to-b;
(function () {
var t = new Date - s;
if (t >= d) {
n ;
t = d;
el .style[_key] = (isOP ? 'alpha(opacity=' : '') Tween.Linear(t, b, c, d) (key != 'opacity' ? 'px' : '') (isOP ? ' )' : '');
!!cb && cb.apply(el);
if (m == n && _this.animQueue.length > 1) {
_this.animQueue.shift( );
_this.execute(_this.animQueue);
返回;
}
el.style[_key] = (isOP ? 'alpha(opacity=' : '') Tween[tw][ease](t, b, c, d) (key != 'opacity' ? 'px' : '') (isOP ? ')' : ''); >if (!HR.timers[el.id]) HR.timers[el.id] = []
HR.timers[el.id].push(setTimeout(arguments.callee, 16)); 🎜>
})();
},
_q = this.animQueue[0];
return this.each(function (el) {
for (var k in _q.config) {
m ;
_anim(el,
k,
k == 'opacity' && !HR.support.opacity ? HR.getStyle('filter', el) == '' ? 100 : parseInt(HR.getStyle('filter', el).match(/d{1, 3}/g)[0]) : HR.getStyle(k, el),
_q.config[k],
typeof _q.time == 'number' ? _q.time : 1000,
typeof _q.tween == 'string' && !/^ease*/.test(_q.tween) ? _q.tween : 'Quart',
typeof _q.ease == 'string' && /^ease* /.test(_q.ease) ? _q.ease : 'easeOut',
_q.callback)
}
});
}
}
HR.extend(HR, {
get : function () {
返回新的 get(参数);
},
isFunction : function(o) {
return typeof(o) == 'function' && (!Function.prototype.call || typeof(o.call) == 'function')
},
getStyle : function (p, el) {
返回 el.currentStyle ? function () {
try {
var d = document.createElement('div');
d.style['display'] = 'none';
d.innerHTML = '';
var a = d.getElementsByTagName('a')[0];
return {
不透明度: a.style.opacity === '0.5'
}
} 最后 {
d = null;
}
})(),
计时器 : { }
});
})();
然后为了让大家看的直观一点,小做了两个demo
【demo1】
如需引入外部Js需刷新才能执行
]
[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

实现方法:1、用“$("img").delay(毫秒数).fadeOut()”语句,delay()设置延迟秒数;2、用“setTimeout(function(){ $("img").hide(); },毫秒值);”语句,通过定时器来延迟。

区别:1、axios是一个异步请求框架,用于封装底层的XMLHttpRequest,而jquery是一个JavaScript库,只是顺便封装了dom操作;2、axios是基于承诺对象的,可以用承诺对象中的方法,而jquery不基于承诺对象。

增加元素的方法:1、用append(),语法“$("body").append(新元素)”,可向body内部的末尾处增加元素;2、用prepend(),语法“$("body").prepend(新元素)”,可向body内部的开始处增加元素。

修改方法:1、用css()设置新样式,语法“$(元素).css("min-height","新值")”;2、用attr(),通过设置style属性来添加新样式,语法“$(元素).attr("style","min-height:新值")”。

删除方法:1、用empty(),语法“$("div").empty();”,可删除所有子节点和内容;2、用children()和remove(),语法“$("div").children().remove();”,只删除子元素,不删除内容。

在jquery中,apply()方法用于改变this指向,使用另一个对象替换当前对象,是应用某一对象的一个方法,语法为“apply(thisobj,[argarray])”;参数argarray表示的是以数组的形式进行传递。

去掉方法:1、用“$(selector).removeAttr("readonly")”语句删除readonly属性;2、用“$(selector).attr("readonly",false)”将readonly属性的值设置为false。

on()方法有4个参数:1、第一个参数不可省略,规定要从被选元素添加的一个或多个事件或命名空间;2、第二个参数可省略,规定元素的事件处理程序;3、第三个参数可省略,规定传递到函数的额外数据;4、第四个参数可省略,规定当事件发生时运行的函数。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Dreamweaver Mac版
视觉化网页开发工具