jquery插件unobtrusive实现片段式加载


Posted in Javascript onJune 15, 2015

废话不多说,首先把源码分享给大家。

//ajax支持库
/*!
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/

/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global window: false, jQuery: false */
/*
data-ajax=true //开启绑定
data-ajax-mode//更新的形式 BEFORE插入到对象之前 AFTER插入到对象之后 为空就是覆盖
data-ajax-update//更新的对象
data-ajax-confirm//设置一个确定取消弹出框的文字,没有则不设置
data-ajax-loading//显示loading的对象
data-ajax-loading-duration//持续时间 默认是0
data-ajax-method//提交方式
data-ajax-url//提交url
data-ajax-begin//ajax前触发的函数或者一段程序
data-ajax-complete//完成后(函数),此时还没有加载返回的数据,请求成功或失败时均调用
data-ajax-success//成功(函数),加载完成的数据
data-ajax-failure//失败,error

*/

(function ($) {
  var data_click = "unobtrusiveAjaxClick",
    data_validation = "unobtrusiveValidation";
  //第二核心,判断是否函数,不是则构造一个匿名函数
  function getFunction(code, argNames) {
    var fn = window, parts = (code || "").split(".");
    while (fn && parts.length) {
      fn = fn[parts.shift()];
    }//查找函数名有时候是命名空间比如xxx.xxx
    if (typeof (fn) === "function") {
      return fn;
    }
    argNames.push(code);
    //如果不是函数对象则自己构造一个并返回,吊!
    return Function.constructor.apply(null, argNames);
  }

  function isMethodProxySafe(method) {
    return method === "GET" || method === "POST";
  }
  //可以添加各种提交方式,应该是为Web Api做的补充
  function asyncOnBeforeSend(xhr, method) {
    if (!isMethodProxySafe(method)) {
      xhr.setRequestHeader("X-HTTP-Method-Override", method);
    }
    //注:X-HTTP-Method-Override是一个非标准的HTTP报头。
    //这是为不能发送某些HTTP请求类型(如PUT或DELETE)的客户端而设计的
  }
  //完成后的
  function asyncOnSuccess(element, data, contentType) {
    var mode;

    if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
      return;
    }

    mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
    $(element.getAttribute("data-ajax-update")).each(function (i, update) {
      var top;

      switch (mode) {
      case "BEFORE":
        top = update.firstChild;
        $("<div />").html(data).contents().each(function () {
          update.insertBefore(this, top);
        });
        break;
      case "AFTER":
        $("<div />").html(data).contents().each(function () {
          update.appendChild(this);
        });
        break;
      default:
        $(update).html(data);
        break;
      }
    });
  }
  //主要函数
  //绑定的对象和参数
  function asyncRequest(element, options) {
    var confirm, loading, method, duration;

    confirm = element.getAttribute("data-ajax-confirm");
    if (confirm && !window.confirm(confirm)) {
      return;
    }

    loading = $(element.getAttribute("data-ajax-loading"));//
    duration = element.getAttribute("data-ajax-loading-duration") || 0;//默认是0

    $.extend(options, {
      type: element.getAttribute("data-ajax-method") || undefined,
      url: element.getAttribute("data-ajax-url") || undefined,
      beforeSend: function (xhr) {//ajax前触发,此处的xhr将在下面用apply传递出去
        var result;
        asyncOnBeforeSend(xhr, method);//判断是否添加特种的提交方式
        result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);//argument:替换函数对象的其中一个属性对象,存储参数。这里是将原先的参数传递出去,吊!
        if (result !== false) {
          loading.show(duration);
        }
        return result;
      },
      complete: function () {
        loading.hide(duration);
        getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
      },
      success: function (data, status, xhr) {
        asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
        getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
      },
      error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
    });

    options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });

    method = options.type.toUpperCase();//大写
    if (!isMethodProxySafe(method)) {
      options.type = "POST";
      options.data.push({ name: "X-HTTP-Method-Override", value: method });
    }
    //最后都是调用jquery的ajax
    $.ajax(options);
  }

  function validate(form) {
    //可以取消验证
    var validationInfo = $(form).data(data_validation);
    return !validationInfo || !validationInfo.validate || validationInfo.validate();
  }


  
  $(document).on("click", "a[data-ajax=true]", function (evt) {
    evt.preventDefault();
    asyncRequest(this, {
      url: this.href,
      type: "GET",
      data: []
    });
  });

  $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {//这个不常用
    var name = evt.target.name,
      $target = $(evt.target),
      form = $target.parents("form")[0],
      offset = $target.offset();

    $(form).data(data_click, [
      { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
      { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
    ]);

    setTimeout(function () {
      $(form).removeData(data_click);
    }, 0);
  });

  $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
    var name = evt.target.name,
      form = $(evt.target).parents("form")[0];

    $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);

    setTimeout(function () {
      $(form).removeData(data_click);
    }, 0);
  });

  $(document).on("submit", "form[data-ajax=true]", function (evt) {
    var clickInfo = $(this).data(data_click) || [];
    evt.preventDefault();
    if (!validate(this)) {
      return;
    }
    asyncRequest(this, {
      url: this.action,
      type: this.method || "GET",
      data: clickInfo.concat($(this).serializeArray())//写得好,序列化表单并拼接,以后的ajax都可以这样,方便啊
    });
  });
  //扩展
  function bindDataAjax(obj) {
    $(obj).on("click", "a[data-ajax=true]", function (evt) {
      evt.preventDefault();
      asyncRequest(this, {
        url: this.href,
        type: "GET",
        data: []
      });
    });

    $(obj).on("click", "form[data-ajax=true] input[type=image]", function (evt) {//这个不常用
      var name = evt.target.name,
        $target = $(evt.target),
        form = $target.parents("form")[0],
        offset = $target.offset();

      $(form).data(data_click, [
        { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
        { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
      ]);

      setTimeout(function () {
        $(form).removeData(data_click);
      }, 0);
    });

    $(obj).on("click", "form[data-ajax=true] :submit", function (evt) {
      var name = evt.target.name,
        form = $(evt.target).parents("form")[0];

      $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);

      setTimeout(function () {
        $(form).removeData(data_click);
      }, 0);
    });

    $(obj).on("submit", "form[data-ajax=true]", function (evt) {
      var clickInfo = $(this).data(data_click) || [];
      evt.preventDefault();
      if (!validate(this)) {
        return;
      }
      asyncRequest(this, {
        url: this.action,
        type: this.method || "GET",
        data: clickInfo.concat($(this).serializeArray())//写得好,序列化表单并拼接,以后的ajax都可以这样,方便啊
      });
    });
  }
  $.fn.unobtrusive = function (option, param) {
    if (typeof options == "string") {
      return $.fn.unobtrusive.methods[options](this, param);
    }
    
  }
  //方法
  $.fn.unobtrusive.methods = {
    resetbind: function (jq) {//对应的对象重新初始化
      return jq.each(function () {
        //bindDataAjax($(this), obj);
        //bindDataAjax(obj);
        bindDataAjax(jq);
      });
    }
  }
}(jQuery));

在出现//扩展字样的地方开始就是我写的扩展,不妨碍原先的代码(尽量不修改别人的代码是我的原则,也是对别人的尊重)。函数主要是提供指定区域的代码绑定,使用方法

$(obj).unobtrusive('resetbind')

需要绑定的地方的DOM对象绑定。比如片段式加载一个页面

<a href="javascript:;" data-ajax-mode="" data-ajax-update=".down-content" data-ajax="true" data-ajax-method="get" data-ajax-url="/Admin/UserAdd" data-ajax-loading="#load"  data-ajax-success="$('.down-content').unobtrusive('resetbind')">添加</a>

将Ajax后的代码加载到.down-content的容器内,然后渲染绑定他们(其实如UI中的easyui也是这样干的)

在片段式加载的方法中我提及一下jquery的load也可以实现,我之前再博客中开源的MvcAdmin就是使用load,但是归根结底还是jquery的html方法。load内部就是对Ajax的封装,然后用html加载到页面上去,load的源码中好像这样写的http://www.css88.com/tool/jQuerySourceViewer/#v=1.7.2&fn=jQuery.fn.load

特别提醒

data-ajax-begin//ajax前触发的函数或者一段程序

data-ajax-complete//完成后,此时还没有加载返回的数据,请求成功或失败时均调用

data-ajax-success//成功,加载完成的数据

这三个的参数的调用的函数必须是字符串,不需要()。比如data-ajax-begin="函数名",不是data-ajax-begin="函数名()",对,不需要括号!

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
通过 Dom 方法提高 innerHTML 性能
Mar 26 Javascript
javascript 读取XML数据,在页面中展现、编辑、保存的实现
Oct 27 Javascript
JavaScript中的类继承
Nov 25 Javascript
javascript确认框的三种使用方法
Dec 17 Javascript
Jquery 在页面加载后执行的几种方式
Mar 14 Javascript
jQuery实现的fixedMenu下拉菜单效果代码
Aug 24 Javascript
JS实现超精简响应鼠标显示二级菜单代码
Sep 12 Javascript
Javascript中的几种继承方式对比分析
Mar 22 Javascript
使用JS正则表达式 替换括号,尖括号等
Nov 29 Javascript
axios学习教程全攻略
Mar 26 Javascript
JS检索下拉列表框中被选项目的索引号(selectedIndex)
Dec 17 Javascript
js实现时间日期校验
May 26 Javascript
js预加载图片方法汇总
Jun 15 #Javascript
jquery实现兼容IE8的异步上传文件
Jun 15 #Javascript
JavaScript中使用Math.floor()方法对数字取整
Jun 15 #Javascript
jQuery实现自动调整字体大小的方法
Jun 15 #Javascript
JavaScript中使用指数方法Math.exp()的简介
Jun 15 #Javascript
Jquery简单实现GridView行高亮的方法
Jun 15 #Javascript
简介JavaScript中Math.cos()余弦方法的使用
Jun 15 #Javascript
You might like
PHP 进程锁定问题分析研究
2009/11/24 PHP
php抓取页面与代码解析 推荐
2010/07/23 PHP
解决Codeigniter不能上传rar和zip压缩包问题
2014/03/07 PHP
PHP合并两个或多个数组的方法
2019/01/20 PHP
html下载本地
2006/06/19 Javascript
javaScript 数值型和字符串型之间的转换
2009/07/25 Javascript
关于Jqzoom的使用心得 jquery放大镜效果插件
2010/04/12 Javascript
用JavaScript玩转游戏物理(一)运动学模拟与粒子系统
2010/06/19 Javascript
js 链式延迟执行DOME
2012/01/04 Javascript
JavaScript中几个重要的属性(this、constructor、prototype)介绍
2013/05/19 Javascript
jQuery实现复选框成对选择及对应取消的方法
2015/03/03 Javascript
JS操作XML实例总结(加载与解析XML文件、字符串)
2015/12/08 Javascript
Javascript实现图片懒加载插件的方法
2016/10/20 Javascript
[原创]SyntaxHighlighter自动识别并加载脚本语言
2017/02/07 Javascript
jquery PrintArea 实现票据的套打功能(代码)
2017/03/17 Javascript
ReactNative列表ListView的用法
2017/08/02 Javascript
javaScript字符串工具类StringUtils详解
2017/12/08 Javascript
JavaScript常用数学函数用法示例
2018/05/14 Javascript
JavaScript实现alert弹框效果
2020/11/19 Javascript
Python实现遍历windows所有窗口并输出窗口标题的方法
2015/03/13 Python
Python检测数据类型的方法总结
2019/05/20 Python
基于Python+Appium实现京东双十一自动领金币功能
2019/10/31 Python
Pandas —— resample()重采样和asfreq()频度转换方式
2020/02/26 Python
浅谈opencv自动光学检测、目标分割和检测(连通区域和findContours)
2020/06/04 Python
利用CSS3实现毛玻璃效果示例源码
2016/09/25 HTML / CSS
纯CSS3制作的鼠标悬停时边框旋转
2017/01/03 HTML / CSS
Html5 audio标签样式的修改
2016/01/28 HTML / CSS
美国派对用品及装饰品网上商店:Shindigz
2016/07/30 全球购物
日本面向世界,国际级的免税在线购物商城:DOKODEMO
2017/02/01 全球购物
英国复古皮包品牌:Beara Beara
2018/07/18 全球购物
澳大利亚电商Catch新西兰站:Catch.co.nz
2020/05/30 全球购物
SQL注入攻击的种类有哪些
2013/12/30 面试题
毕业生求职自荐书范文
2014/03/27 职场文书
汽车技术服务与贸易专业求职信
2014/07/20 职场文书
还在手动盖楼抽奖?教你用Python实现自动评论盖楼抽奖(一)
2021/06/07 Python
python中__slots__节约内存的具体做法
2021/07/04 Python