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 相关文章推荐
Jquery AJAX 用于计算点击率(统计)
Jun 30 Javascript
JavaScript 学习历程和心得分享
Dec 12 Javascript
Js实现滚动变色的文字效果
Jun 16 Javascript
jquery用offset()方法获得元素的xy坐标
Sep 06 Javascript
js 实现一些跨浏览器的事件方法详解及实例
Oct 27 Javascript
Reactjs实现通用分页组件的实例代码
Jan 19 Javascript
vue计算属性时v-for处理数组时遇到的一个bug问题
Jan 21 Javascript
关于微信小程序bug记录与解决方法
Aug 15 Javascript
angularjs1.5 组件内用函数向外传值的实例
Sep 30 Javascript
Vue源码中要const _toStr = Object.prototype.toString的原因分析
Dec 09 Javascript
vue-router 路由传参用法实例分析
Mar 06 Javascript
多页vue应用的单页面打包方法(内含打包模式的应用)
Jun 11 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和XSL stylesheets转换XML文档
2006/10/09 PHP
谈谈新手如何学习PHP
2006/12/14 PHP
PHP 数组教程 定义数组
2009/10/23 PHP
处理单名多值表单的详解
2013/06/08 PHP
ThinkPHP的截取字符串函数无法显示省略号的解决方法
2014/06/25 PHP
laravel 5.3中自定义加密服务的方案详解
2017/05/09 PHP
PHP基于进程控制函数实现多线程
2020/12/09 PHP
Asp.net下使用Jquery Ajax传送和接收DataTable的代码
2010/09/12 Javascript
同时使用n个window onload加载实例介绍
2013/04/25 Javascript
PHP配置文件php.ini中打开错误报告的设置方法
2015/01/09 PHP
JS模仿编辑器实时改变文本框宽度和高度大小的方法
2015/08/17 Javascript
轻松搞定jQuery.noConflict()
2016/02/15 Javascript
全面介绍javascript实用技巧及单竖杠
2016/07/18 Javascript
AngularJS 中的事件详解
2016/07/28 Javascript
JavaScript 中有关数组对象的方法(详解)
2016/08/15 Javascript
AngularJS使用ng-repeat指令实现下拉框
2016/08/23 Javascript
nodejs个人博客开发第五步 分配数据
2017/04/12 NodeJs
vue组件讲解(is属性的用法)模板标签替换操作
2020/09/04 Javascript
vue 微信分享回调iOS和安卓回调出现错误的解决
2020/09/07 Javascript
python对象及面向对象技术详解
2016/07/19 Python
pandas数据预处理之dataframe的groupby操作方法
2018/04/13 Python
pycharm 取消默认的右击运行unittest的方法
2018/11/29 Python
Python OpenCV对本地视频文件进行分帧保存的实例
2019/01/08 Python
Python 保持登录状态进行接口测试的方法示例
2019/08/06 Python
python 实现将Numpy数组保存为图像
2020/01/09 Python
Python列表操作方法详解
2020/02/09 Python
python字符串判断密码强弱
2020/03/18 Python
基于Python 的语音重采样函数解析
2020/07/06 Python
常用的HTML5列表标签
2017/06/20 HTML / CSS
德国BA保镖药房韩文网:kr.ba.de
2017/09/04 全球购物
《蚕姑娘》教学反思
2014/04/15 职场文书
会计毕业生自荐书
2014/06/12 职场文书
元旦晚会活动总结
2014/07/09 职场文书
2014年涉外离婚协议书范本
2014/11/20 职场文书
学长教您写论文:经验总结
2019/07/09 职场文书
MySQL串行化隔离级别(间隙锁实现)
2022/06/16 MySQL