文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>如jQuery般易用的api风格

如jQuery般易用的api风格

时间:2011-01-21  来源:岑安

    回到正题,如jQuery般易用的api风格?那到底是什么样的风格呢?个人觉得比较重要的有两点,一是对dom操作的链式调用,并且都呈队列状态,不仅仅使代码的可读语义变得通俗易懂,而且省去了对同一dom元素的多个链式操作时的回调中嵌回调的方式,这是很重要的一点。
    二是对元素的批量操作,这是建立在它强大的选择器上的。jq选择器很强大,这是人所众知的,就不多说了。而且肯定也不是一两天就能实现的了的,所以下面就对我所说的这两点谈谈我的看法。

    基于它强大的选择器,jquery所有的dom操作都依赖于根据它选择器取到的一个数组,很多人喜欢把这叫做jq对象。那咱们暂时也先这样叫吧。然后所有的dom操作都是依赖于这个jq对象中每一个元素并发批量执行的。具体到每一个dom操作,大部分的都是呈链式回调的状态,也就是说在这个方法链里面,直接根据方法调用在链中的先后顺序就能知道他们执行的顺序。这种方法链并且串行的形式是它的一大特色。

    以至于很多人喜欢用jquery,基本就看中它两点,选择器确实很强大,链式调用确实很方便很易用,代码逻辑瞬间变得简单。正因为他把很多的代码逻辑都放到自己内部去处理了,留给编码者考虑的问题就少了很多,所以一方面你觉得好用的同时,也就失去了一次锻炼编码逻辑的机会。因此我不建议初学者直接学习使用jquery或者其他的框架,因为他们会让你对js的理解越来越少。我的观点是所有的框架或者库都是拿来使用的,拿来提高开发效率和管理便利度的,而不是拿来学习的。(当然,研究源码的除外)。

    那么,既然觉得jquery的api风格好用,那我们何尝不尝试一下构建这种类似的api风格呢?(声明:以下尝试都仅仅是提供一种思路,代码并不完善...)
    首先像jquery一样获取一个dom对象的列表。咱们暂时就基于id来获取元素吧。

    var get = function (ids) {
        var d = document, a = -1;
        this.elements = [];
        if (typeof ids != 'string' && !!ids.length) {
            for (var i=0; i<ids.length; i++) {
                var id = ids[i], o;
                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<this.elements.length; i++) {
                fn.call(this, this.elements[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<HR.timers[el.id].length; i++) clearTimeout(HR.timers[el.id][i])
            });
            return this;
        },
针对不同的dom元素id设置专门的临时计时器存贮,HR.timers[el.id],然后遍历当前dom列表,把对应的计时器clear掉。参数clearQueue作为可选参数,用来控制是否清掉后续等待执行的animate。

 

    为了让这个方法更加好玩一点,我加了几种额外的缓动方式,jquery只有一种swing,然后所有的缓动算法放置在Tween对象中以供使用。下面是我做测试的源码,(如有纰漏,各位见谅)

代码 /* =========== animate js ============ */
/*       @author:hongru.chen           */
/* =================================== */

if (typeof HR == '#ff0000' || !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) < 1) return c/2*t*t + b;
                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) < 1) return c/2*t*t*t + b;
                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) < 1) return c/2*t*t*t*t + b;
                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) < 1) return c/2*t*t*t*t*t + b;
                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) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
                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) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
                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 < Math.abs(c)) { a=c; var s=p/4; }
                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 < Math.abs(c)) { a=c; var s=p/4; }
                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 < Math.abs(c)) { a=c; var s=p/4; }
                else var s = p/(2*Math.PI) * Math.asin (c/a);
                if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
                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) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
                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) < (1/2.75)) {
                    return c*(7.5625*t*t) + b;
                } else if (t < (2/2.75)) {
                    return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
                } else if (t < (2.5/2.75)) {
                    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 < d/2) return Tween.Bounce.easeIn(t*2, 0, c, d) * .5 + b;
                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<ids.length; i++) {
                var id = ids[i], o;
                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<this.elements.length; i++) {
                fn.call(this, this.elements[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<HR.timers[el.id].length; i++) clearTimeout(HR.timers[el.id][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 = '<a style="float:left; opacity:.5;"></a>';
                var a = d.getElementsByTagName('a')[0];
                return {
                    opacity: a.style.opacity === '0.5'
                }
            } finally {
                d = null;
            }
        })(),
        
        timers : {}

    });

 然后为了让大家看的直观一点,小做了两个demo
【demo1】
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> #me, #you { border: 2px solid #333; margin-bottom: 10px; position: absolute; overflow: hidden; } #me {left:0; top: 0} #you {left:0; top: 300px} </style> </head> <body> <div id="me" style="width:300px">fasdf<br/>fasdf<br/>fasdf<br/>fasdf<br/>fasdf<br/>fasdf<br/></div> <div id="you">fasdf<br/>fasdf<br/></div> <input type="button" value="stop" style="margin-top:600px" onclick="HR.get('me','you').stop().animate({top:100})" /> </body> </html>


【demo2】
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Super Animate</title> <meta name="Author" content="hongru.chen" /> <style type="text/css"> html, body {overflow:hidden} body, h1, h2, h3, h4, h5, h6, p, ul, dl, ol {margin:0; padding:0} li {list-style:none} body { color: #fff; font: 14px/1.5 'ChunkFive Regular', Arial, Helvetica, sans-serif;} .mask {position: absolute; background:#000; width: 100%; left:0; top: 0; z-index:999} #start {position: absolute; color:#000; font-size:50px; top: 45%; opacity:0; filter:alpha(opacity=0)} .bg {position:absolute; background:url(http://images.cnblogs.com/cnblogs_com/hongru/280894/o_bg-1.jpg) 50% 50%; left:0; width: 100%} #menu dl {padding: 14px 8px 2px 8px} #menu {position: absolute; background: #000; font-size: 30px; left: 100px;top:120px; overflow:hidden;height:0; width:176px; z-index:1000} #menu dd {font-weight: bold; cursor:pointer; height: 44px;overflow:hidden; position:relative} #menu dd ul {position: absolute;left:0;top:0} .color-1 {color:#d61565} .color-2 {color:#555;} .info {position: absolute; width: 300px; left:300px; top: 120px;padding:14px 10px;background: #000;overflow:hidden;width:0;height:30px;display:none;z-index:1000} .fs-12 {font-size:12px} #waiting {left: 46%; top:46%;font-size:40px; color:#999;position:absolute} </style> </head> <body> <div id="menu"> <dl> <dt><em>岑安 --</em></dt> <dd><ul id="menu0"> <li>home</li> <li class="color-1">home</li> </ul></dd> <dd> <ul id="menu1"> <li>info</li> <li class="color-1">info</li> </ul> </dd> <dd> <ul id="menu2"> <li>gallery</li> <li class="color-1">gallery</li> </ul> </dd> <dd> <ul id="menu3"> <li>blog</li> <li class="color-1">blog</li> </ul> </dd> <dd> <ul id="menu4"> <li>contact</li> <li class="color-1">contact</li> </ul> </dd> </dl> </div> <div id="info0" class="info"> <p class="color-2"><em>This is Hongru's space <span class="color-1">-- home</span><br/>@me: [email protected]</em></p> <strong class="color-1">Welcome !</strong><br/> <p class="fs-12">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque cor rupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.<br/><br/>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br/><br/> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <div id="info1" class="info"> <p class="color-2"><em>This is Hongru's space <span class="color-1">-- info</span><br/>@me: [email protected]</em></p> <strong class="color-1">Welcome !</strong><br/> <p class="fs-12">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque cor rupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.<br/><br/>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br/><br/> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <div id="info2" class="info"> <p class="color-2"><em>This is Hongru's space <span class="color-1">-- gallery</span><br/>@me: [email protected]</em></p> <strong class="color-1">Welcome !</strong><br/> <p class="fs-12">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque cor rupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.<br/><br/>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br/><br/> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <div id="info3" class="info"> <p class="color-2"><em>This is Hongru's space <span class="color-1">-- blog</span><br/>@me: [email protected]</em></p> <strong class="color-1">Welcome !</strong><br/> <p class="fs-12">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque cor rupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.<br/><br/>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br/><br/> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <div id="info4" class="info"> <p class="color-2"><em>This is Hongru's space <span class="color-1">-- contact</span><br/>@me: [email protected]</em></p> <strong class="color-1">Welcome !</strong><br/> <p class="fs-12">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque cor rupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.<br/><br/>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br/><br/> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <div id="bg" class="bg"> </div> <div id="mask" class="mask"><strong id="waiting">Waiting...</strong></div> <em id="start">Start!</em> </body> </html>

 


相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载