jQuery返回定位插件详解


Posted in jQuery onMay 15, 2017

一、jQuery 提供开发者开发插件的几种模式

1.$.extend();     //这个方法是绑定在$上面的。可以通过$直接调用

2.$.fn.方法名     //这个方法是绑定在Dom对象上面的可以通过$('').方法名();调用

3.$.widget   //通过jQuery UI 部件工厂模式创建。

二、插件的开发过程

1.$.extend();

这个方法其实很简单,只是像$上面添加了一个静态的方法而已。主要用途是对插件api的扩展.

eg:

//$.extend();为了防止,变量和方法之间的相互污染,我们采用闭包的模式。
  (function($,factory){
    var obj = factory();
    $.extend({
      sayHelloWorld:obj.firstApply,
    })
    $.secondApply = obj.secondApply;
  })(jQuery,function(){
    var obj = {
      firstApply(){
        console.log('hello world');
      },
      secondApply(){
        console.log('直接绑定到$上');
      },
    };
     return obj;
  });
  $.sayHelloWorld();//hello world
  $.secondApply(); //直接绑定到$上
   /*从上面的2种绑定方式可以看出用$.extend();对jQuery方法进行拓展,
   其实和直接绑定到$上是一样的效果*/

2.$.fn.方法名。   (方法名 其实就是插件名)。

a.插件结构

<div id="app">app</div>
//$.fn.插件名字 (logText);
  (function($,factory){

    $.fn.logText = factory();
  })(jQuery,function(){
    var logText = function(){
      console.log(this.text());
      return this;
    }
    return logText;
  });
$("#app").logText(); //app  通过DOM元素之间调用该方法。并返回该对象。这也是jQuery实现链式操作的技巧。
  var h = $("#app").logText().height(); // app
  console.log(h); //18
 //这样就可以自定义方法了。

在jQuery插件的开发过程中,其实主要是通过第二种模式($.fn.插件名)开发的。因为jQuery的强大之处就是对Dom的操作.

b.一个插件的强大之处就是参提供周全的参数。以及方便使用者对参数进行扩展。

<div id="app">app</div>
   //$.fn.插件名字 (myPuglin);
  (function(global,$,factory){
    var common = factory(); //封装插件使用到的函数。
    $.fn.myPuglin = function(opts){  //插件的名称
      var defaults = {}; //默认的api
      opts = $.extend(defaults,opts || {}); //对api的拓展
      /*
       *
       * 要执行的功能
       * 
       */
      console.log(opts.hello);

      return this;
    }
  })(window,jQuery,function(){
    var common = {
      a(opt){
        return opt;
      },
    };
    return common;
  });
  $("#app").myPuglin({hello:'hello world'}); //hello world

准备工作已经完毕。那么下面会一个插件为列子,来讲解

3.工作中经常用到的列表到详情。返回来需要保留该位置的插件。(返回定位) savePositon();  $.fn.savePosition

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <title>Title</title>
  <style>
    @media screen and (max-width: 319px) {
      html {
        font-size: 85.33333px; } }
    @media screen and (min-width: 320px) and (max-width: 359px) {
      html {
        font-size: 85.33333px; } }
    @media screen and (min-width: 360px) and (max-width: 374px) {
      html {
        font-size: 96px; } }
    @media screen and (min-width: 375px) and (max-width: 383px) {
      html {
        font-size: 100px; } }
    @media screen and (min-width: 384px) and (max-width: 399px) {
      html {
        font-size: 102.4px; } }
    @media screen and (min-width: 400px) and (max-width: 413px) {
      html {
        font-size: 106.66667px; } }
    @media screen and (min-width: 414px) {
      html {
        font-size: 110.4px; } }
    /*CSS Reset*/
    body,
    div,
    dl,
    dt,
    dd,
    ul,
    ol,
    li,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6,
    pre,
    code,
    form,
    fieldset,
    legend,
    input,
    textarea,
    p,
    blockquote,
    th,
    td,
    header,
    hgroup,
    nav,
    section,
    article,
    aside,
    footer,
    figure,
    figcaption,
    menu,
    button {
      margin: 0;
      padding: 0; }
    li{
      list-style: none;
    }
    #app{
      width: 100%;
      max-width: 640px;
     }
    li {
      height: 1.2rem;
      width: 100%;
      border-bottom: 1px solid #cccccc;
      text-align: center;
      line-height: 1.2rem;
      font-size: 20px;
    }
  </style>
  <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

</head>
<body>
  <div id="app">
    <ul>
      <li data-page="1" data-url="http://baidu.com?id=1">第一页 第1个li</li>
      <li data-page="1" data-url="http://baidu.com?id=2">第一页 第2个li</li>
      <li data-page="1" data-url="http://baidu.com?id=3">第一页 第3个li</li>
      <li data-page="1" data-url="http://baidu.com?id=4">第一页 第4个li</li>
      <li data-page="1" data-url="http://baidu.com?id=5">第一页 第5个li</li>
      <li data-page="1" data-url="http://baidu.com?id=6">第一页 第6个li</li>
      <li data-page="1" data-url="http://baidu.com?id=7">第一页 第7个li</li>
      <li data-page="1" data-url="http://baidu.com?id=8">第一页 第8个li</li>
      <li data-page="1" data-url="http://baidu.com?id=9">第一页 第9个li</li>
      <li data-page="1" data-url="http://baidu.com?id=10">第一页 第10个li</li>
      <li data-page="1" data-url="http://baidu.com?id=11">第一页 第11个li</li>
      <li data-page="1" data-url="http://baidu.com?id=12">第一页 第12个li</li>
      <li data-page="1" data-url="http://baidu.com?id=13">第一页 第13个li</li>
      <li data-page="1" data-url="http://baidu.com?id=14">第一页 第14个li</li>
      <li data-page="1" data-url="http://baidu.com?id=15">第一页 第15个li</li>

      <li data-page="2" data-url="http://baidu.com?id=16">第二页 第1个li</li>
      <li data-page="2" data-url="http://baidu.com?id=17">第二页 第2个li</li>
      <li data-page="2" data-url="http://baidu.com?id=18">第二页 第3个li</li>
      <li data-page="2" data-url="http://baidu.com?id=19">第二页 第4个li</li>
      <li data-page="2" data-url="http://baidu.com?id=20">第二页 第5个li</li>
      <li data-page="2" data-url="http://baidu.com?id=21">第二页 第6个li</li>
      <li data-page="2" data-url="http://baidu.com?id=22">第二页 第7个li</li>
      <li data-page="2" data-url="http://baidu.com?id=23">第二页 第8个li</li>
      <li data-page="2" data-url="http://baidu.com?id=24">第二页 第9个li</li>
      <li data-page="2" data-url="http://baidu.com?id=25">第二页 第10个li</li>
      <li data-page="2" data-url="http://baidu.com?id=26">第二页 第11个li</li>
      <li data-page="2" data-url="http://baidu.com?id=27">第二页 第12个li</li>
      <li data-page="2" data-url="http://baidu.com?id=28">第二页 第13个li</li>
      <li data-page="2" data-url="http://baidu.com?id=29">第二页 第14个li</li>
      <li data-page="2" data-url="http://baidu.com?id=30">第二页 第15个li</li>
    </ul>
  </div>
</body>
<script type="text/javascript">
  /*
   * 1.为什么我要返回定位呢。肯定是增加用户的体验度。比如你刚看的那条信息挺感
   * 兴趣的,点进详情看完了,回来一看,不见了,是不是很呕心啊。
   * 2.难点在哪里?
   *  难点1:当我们有很多的列表的时候,列表肯定是滚动加载。于是我们直接保存滚动条的位置
   *  的方式可以放弃了。
   *  难点2:我们怎么确定是从详情返回来的?
   * 3.我们该怎么实现呢?
   *  其实我们实现的方式跟保存滚动条的位置差不多。但要对scrollTop的距离进行处理。
   *  a.我们点击这点详情的时候,可视区域列表的条数,可以是一页的数据,可能会是2页数据。
   *  这种情况下我们都要把结果保留下来。
   *  b.当我们点击这条数据的时候存现当前页滚动了多少就可以了。
   *
   *  下面具体看代码:
   */
  (function(global,$,factory){
    var keepScrollTop = 0; //用于最后保存的滚动条的位置
    var tool =factory();
    $.fn.savePosition = function(options){
      var dataPage,logo,objLogo,prevNum,containerHeight = 0,scrollTopDistance = 0,elIndex = 0,
       prevHeight = 0,prevCountPage = 0,prevCountPageDistance = 0,prevDistance = 0,
       prevPageScrollDistance = 0;
      var elements = this;
      var defaults = {
        container:$(window),  //滚动的容器
        logo:"data-url",   // 用于计算在这个容器中的每个LI中的唯一标识量。一般为去详情的连接
        currentPage:"data-page",  //点击当前的li的页码
        pageResize:30,        //与后台交互的每页返回的数量。 默认是30,
        goToDetailElement:$(".go-detail") ,  //滚动的每个列的总对象
        nodeLi:"", //元素节点
        getPageNum:"getPageNum",       //1表示单页数据,2表示双页数据。设置是请求单页数据还是双页数据的标识量。放在URL上。
        urlPageNum:"pageNum",        //用于放到URL上面的参数标识表示当前是几页. pageNum = currentPage  //返回来的时候用这个参数来判断是不是需要滚动
      };
      var settings = $.extend(defaults,options || {});
      dataPage = elements.attr(settings.currentPage);  //求出点击对象位于哪一个页码
      logo = elements.attr(settings.logo);   //求出当前对象的唯一标识量
      containerHeight = parseInt(settings.container.outerHeight());  //容器的高度
      scrollTopDistance = parseInt(settings.container.scrollTop()); //滚动的距离
      elements.parent().find(""+ settings.nodeLi + "["+settings.currentPage + "=" + dataPage +"]").each(function(index, obj){
        objLogo = $(obj).attr(settings.logo);
        elIndex = index;
        if(logo == objLogo){
          prevNum = elements.prevAll().length;
          prevHeight = tool.getDistance(elements.parent().children(),prevNum - elIndex);
          prevCountPage = parseInt(prevNum / settings.pageResize);
          if(scrollTopDistance < prevHeight){
            elements.parent().children().each(function(index,target){
              if(prevCountPage > 0 ){
                if(index < (prevCountPage - 1) * settings.pageResize){
                  prevCountPageDistance += parseInt($(target).outerHeight());
                };
              };
            });
            tool.changeUrlPar(settings.urlPageNum,dataPage - 1);     //当前的页数
            tool.changeUrlPar(settings.getPageNum,2);       //获取双页数据
            keepScrollTop = scrollTopDistance - prevCountPageDistance;          //请求双页数据 向上 减 1;
          }else{
            prevDistance = tool.getDistance(elements.parent().children(),(prevCountPage + 1) * settings.pageResize);
            prevPageScrollDistance = tool.getDistance(elements.parent().children(),prevCountPage * settings.pageResize);
            if(prevDistance < (scrollTopDistance + containerHeight)){
              tool.changeUrlPar(settings.urlPageNum,dataPage);    //点击对象位于当前的页数
              tool.changeUrlPar(settings.getPageNum,2);        //请求双页数据
              keepScrollTop = scrollTopDistance - prevPageScrollDistance;
            }else{
              tool.changeUrlPar(settings.urlPageNum,dataPage);    //点击对象位于当前的页数
              tool.changeUrlPar(settings.getPageNum,1);  //请求单页数据
              keepScrollTop = scrollTopDistance - prevPageScrollDistance;
            };
          };
        };
      });
      tool.setSessionStorage("keepScrollTop",keepScrollTop);   //保存滚动条的位置
      return this;
    };
    $.getSessionStorage = function(opt){
      opt = sessionStorage.getItem(opt);
      return opt;
    };
  })(window,jQuery,function(){
    var tool = {
      changeUrlPar(arg, val){  //改变URL参数
        function changeU(destiny, par, par_value) {
          var pattern = par+'=([^&]*)';
          var replaceText = par+'='+par_value;
          if (destiny.match(pattern))
          {
            var tmp = '/\\'+par+'=[^&]*/';
            tmp = destiny.replace(eval(tmp), replaceText);
            return (tmp);
          }
          else {
            if (destiny.match('[\?]'))
            {
              return destiny+'&'+ replaceText;
            }
            else
            {
              return destiny+'?'+replaceText;
            }
          }
          return destiny+'\n'+par+'\n'+par_value;
        }
        var hash = window.location.hash;
        history.replaceState(null,'',location.pathname+location.search);
        url = window.location.href;
        var newUrl = changeU(url,arg,val) + hash;
        history.replaceState(null,'',newUrl);
        return false;
      },
      removeUrlPar(options){
        history.replaceState(null,'',location.pathname+location.search);
        var newParamStr = "";
        var quotes = window.location.href.indexOf("?");
        if(quotes != -1){
          var webUrl = window.location.href.split("?")[0];
          var paramsStr = window.location.href.split("?")[1].toString();
          if(paramsStr.indexOf("&") != -1){
            var pageIndex = paramsStr.indexOf(options);
            if(pageIndex != -1){
              var pageArr = paramsStr.split("&");
              for(var i = 0; i < pageArr.length; i++){
                if(pageArr[i].match(options)){
                  pageArr.splice(i,1);
                };
              };
              newParamStr = pageArr.join("&");
            }else{
              newParamStr = paramsStr;
            } ;

          }else{
            if(paramsStr.match(options)){
              newParamStr = "";
            }else {
              newParamStr = paramsStr;
            };
          };
          history.replaceState(null,'',webUrl + "?" + newParamStr);
        }else{
          history.replaceState(null,'',w.location.href);
        }
      },
      getDistance(obj,maxNum){
        var h = 0;
        obj.each(function(index,target){
          if(index < maxNum){
            h += parseInt($(target).outerHeight());
          }
        });
        return h;
      },
      setSessionStorage(keyName,opt){
        sessionStorage.setItem(keyName,opt);
        console.log(opt)
      },
    }

    return tool;
  })
  $("li").on("click",function(){
    $(this).savePosition({pageResize:15});
    /*
     *  1.http://localhost/index.php/Home/Web?pageNum=2&getPageNum=1
     * 点击玩了以后url就变成这样了。这时候表示 返回来的时候请求第二页的数据。只请求一次。从第二页开始
     *
     * 2.http://localhost/index.php/Home/Web?pageNum=1&getPageNum=2
     * 这样表示请求也数据。从第一页的数据开始
     *
     */
    var _herf = $(this).attr("data-url");
    window.location.href = _herf;
  });
  //当我们初始化的时候
  var pageNum = 1,getPageNum = 2; //这两个数的值是从URL中获取的。只有从详情返回来 时候,才有

  if(!!pageNum && !!getPageNum){
    //其中还有很多判定,肯定是先获取数据在滚动。。。
    $(window).scrollTop($.getSessionStorage('keepScrollTop'));
  }else{

  }
</script>
</html>

这个返回定位的插件基本就开发完毕了。当然对于实际的项目中,还有很多的改动。比如返回的时候,一定要把设置的标志参数去掉。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

jQuery 相关文章推荐
基于JQuery和原生JavaScript实现网页定位导航特效
Apr 03 jQuery
JS与jQuery实现子窗口获取父窗口元素值的方法
Apr 17 jQuery
jQuery 实现图片的依次加载图片功能
Jul 06 jQuery
利用JQUERY实现多个AJAX请求等待的实例
Dec 14 jQuery
jquery自定义显示消息数量
Dec 19 jQuery
基于jQuery的时间戳与日期间的转化
Jun 21 jQuery
详解webpack引用jquery(第三方模块)的三种办法
Aug 21 jQuery
基于JavaScript或jQuery实现网站夜间/高亮模式
May 30 jQuery
jQuery使用jsonp实现百度搜索的示例代码
Jul 08 jQuery
jquery实现简易验证插件封装
Sep 13 jQuery
多种类型jQuery网页验证码插件代码实例
Jan 09 jQuery
jQuery ajax - getScript() 方法和getJSON方法
May 14 jQuery
jQuery操作css样式
May 15 #jQuery
jQuery插件FusionCharts绘制的2D条状图效果【附demo源码】
May 13 #jQuery
jQuery插件FusionCharts绘制的2D双柱状图效果示例【附demo源码】
May 13 #jQuery
jQuery中clone()函数实现表单中增加和减少输入项
May 13 #jQuery
jQuery遍历节点方法汇总(推荐)
May 13 #jQuery
jQuery手风琴的简单制作
May 12 #jQuery
jQuery.ajax向后台传递数组问题的解决方法
May 12 #jQuery
You might like
PHP使用Memcache时模拟命名空间及缓存失效问题的解决
2016/02/27 PHP
PHP基于堆栈实现的高级计算器功能示例
2017/09/15 PHP
thinkPHP5框架分页样式类完整示例
2018/09/01 PHP
JS字符串处理实例代码
2013/08/05 Javascript
JavaScript中的常见问题解决方法(乱码,IE缓存,代理)
2013/11/28 Javascript
JavaScript数组Array对象增加和删除元素方法总结
2015/01/20 Javascript
jQuery结合AJAX之在页面滚动时从服务器加载数据
2015/06/30 Javascript
AngularJS轻松实现双击排序的功能
2016/08/30 Javascript
JS实现表单验证功能(验证手机号是否存在,验证码倒计时)
2016/10/11 Javascript
Angular.JS学习之依赖注入$injector详析
2016/10/20 Javascript
基于jQuery实现左侧菜单栏可折叠功能
2016/12/27 Javascript
微信小程序 用户数据解密详细介绍
2017/01/09 Javascript
利用node.js如何搭建一个简易的即时响应服务器
2017/05/28 Javascript
ES6解构赋值实例详解
2017/10/31 Javascript
[01:46]DOTA2上海特锦赛小组赛英文解说KotlGuy采访
2016/02/27 DOTA
python getopt 参数处理小示例
2009/06/09 Python
Python入门篇之正则表达式
2014/10/20 Python
Python代码解决RenderView窗口not found问题
2016/08/28 Python
python 定时修改数据库的示例代码
2018/04/08 Python
django 多数据库配置教程
2018/05/30 Python
详解pandas使用drop_duplicates去除DataFrame重复项参数
2019/08/01 Python
Python+OpenCV+图片旋转并用原底色填充新四角的例子
2019/12/12 Python
Jupyter notebook设置背景主题,字体大小及自动补全代码的操作
2020/04/13 Python
如何基于Python实现word文档重新排版
2020/09/29 Python
Python实现AES加密,解密的两种方法
2020/10/03 Python
Pandas之缺失数据的实现
2021/01/06 Python
深入浅出CSS3 background-clip,background-origin和border-image教程
2011/01/27 HTML / CSS
CSS3新增布局之: flex详解
2020/06/18 HTML / CSS
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
英国第一独立滑雪板商店:The Snowboard Asylum
2020/01/16 全球购物
Shopbop中文官网:美国亚马逊旗下时尚购物网站
2020/12/15 全球购物
冰淇淋开店创业计划书
2014/02/01 职场文书
体育教学随笔感言
2014/02/24 职场文书
运动会广播稿50字
2015/08/19 职场文书
导游词之广州陈家祠
2019/10/21 职场文书
PyCharm 安装与使用配置教程(windows,mac通用)
2021/05/12 Python