如jQuery般易用的api风格代码分享_javascript技巧
回到正题,如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 else return 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 == 'string' ? d.getElementById(id) : id;
this.elements.push(o);
}
} else {
while (typeof arguments[++a] == 'string') {
this.elements.push(d.getElementById(arguments[a]));
}
}
}
get.prototype = {
each : function (fn) {
for (var i=0; i
}
return this;
},
setStyle : function (p, v) {
this.each(function (el) {
el.style[p] = v;
});
return this;
},
show : function () {
var _this = this;
this.each(function (el) {
_this.setStyle('display', 'block');
})
return this;
},
hide : function () {
var _this = this;
this.each(function (el) {
_this.setStyle('display', 'none');
})
return this;
},
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;
},
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;
},
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)
}
});
}
}
HR.extend(HR, {
get : function () {
return new get(arguments);
},
isFunction : function(o) {
return typeof(o) == 'function' && (!Function.prototype.call || typeof(o.call) == 'function');
},
getStyle : function (p, el) {
return el.currentStyle ? el.currentStyle[p] : document.defaultView.getComputedStyle(el, null).getPropertyValue(p);
},
support : (function () {
try {
var d = document.createElement('div');
d.style['display'] = 'none';
d.innerHTML = '';
var a = d.getElementsByTagName('a')[0];
return {
opacity: a.style.opacity === '0.5'
}
} finally {
d = null;
}
})(),
timers : {}
});
})();
然后为了让大家看的直观一点,小做了两个demo
【demo1】
[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]
【demo2】
[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Comment utiliser la méthode de requête PUT dans jQuery ? Dans jQuery, la méthode d'envoi d'une requête PUT est similaire à l'envoi d'autres types de requêtes, mais vous devez faire attention à certains détails et paramètres. Les requêtes PUT sont généralement utilisées pour mettre à jour des ressources, comme la mise à jour de données dans une base de données ou la mise à jour de fichiers sur le serveur. Ce qui suit est un exemple de code spécifique utilisant la méthode de requête PUT dans jQuery. Tout d'abord, assurez-vous d'inclure le fichier de la bibliothèque jQuery, puis vous pourrez envoyer une requête PUT via : $.ajax({u

Titre : jQuery Astuces : Modifier rapidement le texte de toutes les balises a de la page En développement web, nous avons souvent besoin de modifier et d'exploiter des éléments de la page. Lorsque vous utilisez jQuery, vous devez parfois modifier le contenu textuel de toutes les balises de la page en même temps, ce qui peut économiser du temps et de l'énergie. Ce qui suit explique comment utiliser jQuery pour modifier rapidement le texte de toutes les balises a de la page et donne des exemples de code spécifiques. Tout d'abord, nous devons introduire le fichier de la bibliothèque jQuery et nous assurer que le code suivant est introduit dans la page : <

Analyse de la stratégie d'intégration de l'API Oracle : pour parvenir à une communication transparente entre les systèmes, des exemples de code spécifiques sont nécessaires. À l'ère numérique d'aujourd'hui, les systèmes internes de l'entreprise doivent communiquer entre eux et partager des données, et l'API Oracle est l'un des outils importants pour contribuer à une communication transparente. communication entre les systèmes. Cet article commencera par les concepts et principes de base d'OracleAPI, explorera les stratégies d'intégration d'API et enfin donnera des exemples de code spécifiques pour aider les lecteurs à mieux comprendre et appliquer OracleAPI. 1. API Oracle de base

Oracle est un fournisseur de systèmes de gestion de bases de données de renommée mondiale et son API (Application Programming Interface) est un outil puissant qui aide les développeurs à interagir et à s'intégrer facilement aux bases de données Oracle. Dans cet article, nous approfondirons le guide d'utilisation de l'API Oracle, montrerons aux lecteurs comment utiliser la technologie d'interface de données pendant le processus de développement et fournirons des exemples de code spécifiques. 1.Oracle

Titre : utilisez jQuery pour modifier le contenu textuel de toutes les balises. jQuery est une bibliothèque JavaScript populaire largement utilisée pour gérer les opérations DOM. En développement web, nous rencontrons souvent le besoin de modifier le contenu textuel de la balise de lien (une balise) sur la page. Cet article expliquera comment utiliser jQuery pour atteindre cet objectif et fournira des exemples de code spécifiques. Tout d’abord, nous devons introduire la bibliothèque jQuery dans la page. Ajoutez le code suivant dans le fichier HTML :

Titre : Comment gérer les problèmes d'erreur de l'API Laravel, des exemples de code spécifiques sont nécessaires lors du développement de Laravel, des erreurs d'API sont souvent rencontrées. Ces erreurs peuvent provenir de diverses raisons telles que des erreurs logiques du code du programme, des problèmes de requête de base de données ou des échecs de requête d'API externe. La façon de gérer ces rapports d'erreurs est un problème clé. Cet article utilisera des exemples de code spécifiques pour démontrer comment gérer efficacement les rapports d'erreurs de l'API Laravel. 1. Gestion des erreurs dans Laravel

Comment savoir si un élément jQuery possède un attribut spécifique ? Lorsque vous utilisez jQuery pour exploiter des éléments DOM, vous rencontrez souvent des situations dans lesquelles vous devez déterminer si un élément possède un attribut spécifique. Dans ce cas, nous pouvons facilement implémenter cette fonction à l'aide des méthodes fournies par jQuery. Ce qui suit présentera deux méthodes couramment utilisées pour déterminer si un élément jQuery possède des attributs spécifiques et joindra des exemples de code spécifiques. Méthode 1 : utilisez la méthode attr() et l'opérateur typeof // pour déterminer si l'élément a un attribut spécifique

jQuery est une bibliothèque JavaScript populaire largement utilisée pour gérer la manipulation DOM et la gestion des événements dans les pages Web. Dans jQuery, la méthode eq() est utilisée pour sélectionner des éléments à une position d'index spécifiée. Les scénarios d'utilisation et d'application spécifiques sont les suivants. Dans jQuery, la méthode eq() sélectionne l'élément à une position d'index spécifiée. Les positions d'index commencent à compter à partir de 0, c'est-à-dire que l'index du premier élément est 0, l'index du deuxième élément est 1, et ainsi de suite. La syntaxe de la méthode eq() est la suivante : $("s
