zoukankan      html  css  js  c++  java
  • 记一次工具优化历程

    记一次工具优化历程

    最近公司搞了一系列的专题活动。因为不是公司的主线任务,所以后台的同学支援的也很有限。提供了一系列的ajax接口供前端同学调用,紧赶慢赶也是把工作完满结束。然后回过头来一看,发现很多重复的接口数据调用,并且数据结构也是一样的。后台的同学是把所有的数据字段都发到的前端,所有要用那些字段全凭需要。所以就想能不能进行一次数据接口请求的封装,在下次需要的时候只需要调用然后所有的事情就解决了。这样就可以减轻前端同学重复的垒代码。既然想好了就开始干。

    先理理需求

    • 统一的接口调用
    • 数据与文档组装返回
    • 有请求延时需求

    其实需求很简单,对应的解决方案也没什么挑战难度的。说说我想的具体思路吧!

    1. 首先对于接口的统一调用,就是以参数形式构造函数的方式来触发。
    2. 拿到后台返回值后与dom组装进行,将数据组装为统一的dom结构(因为所有的数据都返回过来了)。对于不需要的数据用css来进行隐藏。
    3. 对于延时请求,首先我想到的是用setTimeout来进行延时。但最终放弃了,感觉这样不太明智(也没什么技术含量,哈哈~)。只是没有将所有请求延后,所以想是否可以到哪个块儿就请求那个块儿的数据。所以想用图片懒加载的思路来解决延时。
      说了这么多还是直接上代码吧。
    var utils = (function(mod) {
    
      /**
       * [ajaxAPI]
       * ajax 获取问文章接口
       * @author mao
       * @version 1
       * @date    2016-09-08
       * @param   {Object}   option {url:请求地址,count:显示条数,elem:dom元素,flag:延时请求true || false,type:class类类型}
       */
      mod.ajaxAPI = function(option) {
        var url  = option.url,
            count = option.count || 3,
            elem = option.elem,
            flag = option.flag || false,
            type = option.type || '';
    
    
        count = parseInt(count);
    
        //判断是否延时
        if(!flag) {
          getData(url, count, elem, type);
        } else {
          //轮动检测
          $(window).scroll(function() {
            //dom块儿是否进入视口
            var Height = $(elem).offset().top - ($(document).scrollTop() + $(elem).height() + $(window).height());
            if(Height < 0) {
              //获取判断参数。为1则不执行,否则执行
              var isDone = $(elem).attr('data-load');
              if(!isDone) {
                //ajax请求
                getData(url, count, elem, type);
                //设置判断参数
                $(elem).attr('data-load', 1);
              }
            }
          });
        }
      }
    
      /**
       * ajax请求数据
       * @author 1
       * @version version
       * @date    2016-09-06
       * @param   {[string]}   url   [请求地址]
       * @param   {[number]}   count [显示条数]
       * @param   {[string]}   elem  [dom元素]
       * @return  {[type]}         [description]
       */
      function getData(url, count, elem, type) {
        $.ajax({
          type:'get',
          url:url,
          dataType:'json',
          success:function(msg) {
            var str = '';
            //判断count是否超过需要的条数
            count = count > msg.length ? msg.length:count; 
            for(var i = 0; i < count; i++) {
              //将数据加载到不同结构的dom中
              str += domType(msg[i], type);
            }
            $(elem).append(str);
          }
        });
      }
    
      /**
       * dom类型结构
       * @author mao
       * @version 1
       * @date    2016-09-07
       * @param   {object}   data 传入数据
       * @param   {number}   type 选择的dom结构
       */
      function domType(data, type) {
    
        var str = '<li class="'+type+'">'+
                    '<a href="'+data.article_url+'" target="_blank">'+
                      '<img src="'+data.thumbnail_url+'">'+
                      '<div>'+
                        '<p>'+data.title+'</p>'+
                        '<span>'+data.digest+'</span>'+
                        '<abbr>'+data.published_at+'</abbr>'+
                        '</div>'+
                    '</a>'+
                  '</li>';
        return str;
      }
    
      return mod;
    
    })(utils || {});
    
    

    这段代码出来之后基本是解决了提出的三个需求,满足实际的要求。对于前端同学的调用也是非常方便的。在跟同事分享之后,同事提了一个问题就是在绑定滚轮事件哪里。在每次调用的都会去绑定事件,相当于会在每一个调用的地方都会绑定一个回调。对于事件绑定的回调消耗会很大,这里可以改进一下。每次调用不去绑定,而是在所有的初始化参数函数准备好后再给予一次绑定,这样就不会有多次绑定事件回调的消耗问题。

    为了解决这个问题,我一开始的思路是将事件绑定在以一个接口开放出来。在所有的函数初始化后再统一调用这个事件绑定。这样就需要将所有的参数暂时保存下来,在需要的时候再去拿。所以我想将他们保存在utils的内部,每次初始化参数一进来就保存。
    修改的绑定部分如下:

    mod.deferScroll = function() {
    	$(window).scroll(function() {
      		//对每一个dom元素进行绑定
      		$.each(obj, function(key, value) {
      			//dom块儿是否进入视口
            var Height = $(value.elem).offset().top - ($(document).scrollTop() + $(value.elem).height() + $(window).height());
            if(Height < 0) {
              //获取判断参数。为1则不执行,否则执行
              var isDone = $(value.elem).attr('data-load');
              if(!isDone) {
                //ajax请求
                //console.log('视口延时', value);
                getData(value);
                //设置判断参数
                $(value.elem).attr('data-load', 1);
              }
            }
      		});
        });
    }
    

    上面代码中的obj就是保存下来的参数数组。
    这样问题又来了,这样就会再向外部开放一个接口。都出来一组调用,对于调用使用就不是很方便了。所以想是否可以将这个函数放在内部,在调用的时候进入一次。所以想到可以这样

    	mod.dataDom = function(option) {
    		option.url  = option.url,
    	    option.count = option.count || 3,
    	    option.elem = option.elem,
    	    option.flag = option.flag || false,
    	    option.type = option.type || '';
    
    	    //存储数据
    		if(option.flag) {
    			obj.push(option);
    		} else {
    			//数据请求
    			getData(option);
    			//console.log('数据请求', option);
    		}
    
    	    //让所有元素准备好,执行一次
    	    if(!static_defer) {
    	      //时间延时
    	      deferTime();
    	      //视口延时
    	      deferScroll();
    	      static_defer = true;
    	    }
    	}
    

    上面代码中多加了个内部变量static_defer,初始值设置为false。这样是指进行一次绑定,但是只有第一个初始化函数能够进入,后面的参数就没有绑定上。怎样才能让所有的参数准备好后才进行绑定。幸运的是javascript的事件循环,能够解决这个问题。将上述代码中加入setTimeout这个定时函数,会将setTimeout里的回调函数放入任务队列中,在主线程执行完之后再执行。这就使能所有的参数保存下来了再进行事件绑定。
    修改如下:

    mod.dataDom = function(option) {
    		option.url  = option.url,
    	    option.count = option.count || 3,
    	    option.elem = option.elem,
    	    option.flag = option.flag || false,
    	    option.type = option.type || '';
    
    	    //存储数据
    		if(option.flag) {
    			obj.push(option);
    		} else {
    			//数据请求
    			getData(option);
    			//console.log('数据请求', option);
    		}
    
    	    //让所有元素准备好,执行一次
    	    if(!static_defer) {
    	      setTimeout(function() {
    	        //时间延时
    	        deferTime();
    	        //视口延时
    	        deferScroll();
    	      }, 0);
    	      static_defer = true;
    	    }
    	}
    

    这样不仅满足了需求,也对事件绑定进行了一次优化。

    参考文档

    JavaScript 运行机制详解:再谈Event Loop
    The Node.js Event Loop, Timers, and process.nextTick()
    Node.js Event Loop 的理解 Timers,process.nextTick()

  • 相关阅读:
    2.WindowsServer2012R2装完的一些友好化设置
    架构畅想:如果以你所会去进行架构,会到哪一步?
    如何导出已有的谷歌插件,又如何把导出的插件安装到360浏览器中,又如何对插件小修小改?
    SQL:指定名称查不到数据的衍伸~空格 换行符 回车符的批量处理
    SVN:服务器资源删掉,本地添加时和删掉的名字同名出现One or more files are in a conflicted state.
    我为NET狂-----大前端专帖
    逆天通用水印扩展篇~新增剪贴板系列的功能和手动配置,卸除原基础不常用的功能
    万恶的剪贴板==》为存储而生
    转帖:DotNet 资源大全中文版
    在不动用sp_configure的情况下,如何 =》去掉列的自增长,并保留原数据
  • 原文地址:https://www.cnblogs.com/marvinemao/p/5875944.html
Copyright © 2011-2022 走看看