• pjax 笔记


    PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片.

    客户端向服务器发送一个普通的请求(1),其实也就是点击了一个链接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。但是这两次请求都让客户端的URL变化了,希望上面的说明可以让你明白了PAJX和AJAX的区别了。

    用法

    1. 引入jquery和jquery.pjax.js
    2. 注册事件
      /**
       * 方式一 按钮父节点监听事件
       *
       * @param selector  触发点击事件的按钮
       * @param container 展示刷新内容的容器,也就是会被替换的部分
       * @param options   参数
       */
      $(document).pjax(selector, [container], options);
      // 方式二 直接对按钮监听,可以不用指定容器,使用按钮的data-pjax属性值查找容器
      $("a[data-pjax]").pjax();
      // 方式三 常规的点击事件监听方式
      $(document).on('click', 'a', $.pjax.click);
      $(document).on('click', 'a', function(event) {
       var container = $(this).closest('[data-pjax-container]');
       $.pjax.click(event, container);
      });
      // 下列是源码中介绍的其他用法,由于本人暂时没有那些需求暂时没深究,有兴趣的各位自己试试看哈
      // 表单提交
      $(document).on('submit', 'form', function(event) {
       var container = $(this).closest('[data-pjax-container]');
       $.pjax.submit(event, container);
      });
      // 加载内容到指定容器
      $.pjax({ url: this.href, container: '#main' });
      // 重新当前页面容器的内容
      $.pjax.reload('#container');

    options默认参数说明

    参数名默认值说明
    timeout 650 ajax 超时时间(单位ms),超时后会执行默认的页面跳转,所以超时时间不应过短,不过一般不需要设置
    push true 使用window.history.pushState改变地址栏url(会添加新的历史记录)
    replace false 使用window.history.replaceState改变地址栏url(不会添加历史记录)
    maxCacheLength 20 缓存的历史页面个数(pjax加载新页面前会把原页面的内容缓存起来,缓存加载后其中的脚本会再次执行)
    version   是一个函数,返回当前页面的pjax-version,即页面中<meta http-equiv="x-pjax-version">标签内容。使用response.setHeader("X-PJAX-Version", "")设置与当前页面不同的版本号,可强制页面跳转而不是局部刷新。
    scrollTo 0 页面加载后垂直滚动距离(与原页面保持一致可使过度效果更平滑)
    type "GET" ajax的参数,http请求方式
    dataType "html" ajax的参数,响应内容的Content-Type
    container   用于查找容器的CSS选择器,[container]参数没有指定时使用
    url link.href 要跳转的连接,默认a标签的href属性
    target link pjax事件参数e的relatedTarget属性,默认为点击的a标签
    fragment   使用响应内容的指定部分(css选择器)填充页面,服务端不进行处理导致全页面请求的时候需要使用该参数,简单的说就是对请求到的页面做截取

    pjax失效情况


    会有一些情况导致pjax失效,下面结合源码分析下(省略部分无关代码)

    function handleClick(event, container, options) {
        ...
    
        // 1. 点击事件的事件源不是a标签。使用a标签可以做到对旧版本浏览器的兼容,所以不建议使用其他标签注册事件
        if (link.tagName.toUpperCase() !== 'A')
            throw "$.fn.pjax or $.pjax.click requires an anchor element"
    
        // 2. 使用鼠标滚轮点击(新标签页打开)
        // 点击超链接的同时按下Shift、Ctrl、Alt和Meta(在Windows键盘中是Windows键,在苹果机中是Cmd键)
        // 作用分别代表新窗口打开、新标签打开(不切换标签)、下载、新标签打开(切换标签)
        if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
            return
    
        // 3. 跨域(网络通讯协议,域名不一致)
        if (location.protocol !== link.protocol || location.hostname !== link.hostname)
            return
    
        // 4. 当前页面的锚点定位
        if (link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location))
            return
    
        // 5. 已经阻止元素发生默认的行为(url跳转)
        if (event.isDefaultPrevented())
            return
    
        ...
    
        var clickEvent = $.Event('pjax:click')
        $(link).trigger(clickEvent, [opts])
    
        // 6. pjax:click事件回调中已经阻止元素发生默认的行为(url跳转)
        if (!clickEvent.isDefaultPrevented()) {
            pjax(opts)
            event.preventDefault()// 阻止url跳转
            $(link).trigger('pjax:clicked', [opts])
        }
    }

    除了上述情况之外,还有下列几种情况:

    • ajax请求失败,或者timeout后请求被中止
    • 当前页面X-PJAX-Version和请求的新页面版本不一致
    • 请求得到完整的页面(包含html标签)却没设置fragment参数

     
    实际操作中出现问题: 
    pajx在浏览器回退和前进是无任何问题的。但如果你进行刷新或F5操作。那么加载出来的页面仅仅为地址栏后台请求出来的页面:比如,如果你的菜单栏项是通过pjax(这里请求的页面dom为 a/list.html)加载对应的内容到指定div(这里假设为div1)。那么如果进行了刷新或F5操作后页面出现的仅仅为 a/list.html页面的布局和信息。如何解决? 
    pajx在提交的头信息中包括了 x-pjax: true

    • 1.服务器端判断是否为x-pjax请求

      服务器后台可通过该字段来判断是否为x-pjax请求。或者自己定义好参数传到后台来区分是否是x-pjax的请求。

    • 2.如果不为x-pjax请求则转发到首页地址

      如果你菜单项的首页为index.html 则转发到该页面。那么在刷新后就能够跳转到首页。包含了菜单项等。

    @Controller
    public class TestController {
        
        @RequestMapping("/")
        public String index(){
            return "index";
        }
        
        @RequestMapping("/data")
        public String test(HttpServletRequest request){
            boolean b = Boolean.valueOf(request.getHeader("x-pjax"));
            if(b){
                
            }else{
                return "redirect:/";
            }
            return "test";
        }
    
    }
     
  • 相关阅读:
    Java 字节码解释说明
    JVM垃圾回收:G1回收器
    JVM 参数
    HotSpot 虚拟机对象探秘
    JDK 内置图形界面工具
    Java 内存模型
    在网络设备上调试 Android 程序
    .NET MVC异步调用中的Session问题
    在MVC的ApiController中实现统一校验
    使用 AndroidX86 在虚拟机中作为调试设备
  • 原文地址:https://www.cnblogs.com/go-skill/p/7613363.html
Copyright © 2020-2023  润新知