zoukankan      html  css  js  c++  java
  • pjax使用小结

    简介


    虽然传统的ajax方式可以异步无刷新改变页面内容,但无法改变页面URL,因此有种方案是在内容发生改变后通过改变URL的hash的方式获得更好的可访问性(如https://liyu365.github.io/BG-UI/tpl/#page/desktop.html),但是hash的方式有时候不能很好的处理浏览器的前进、后退,而且常规代码要切换到这种方式还要做不少额外的处理。而pjax的出现就是为了解决这些问题,简单的说就是对ajax的加强。

    pjax结合pushState和ajax技术, 不需要重新加载整个页面就能从服务器加载Html到你当前页面,这个ajax请求会有永久链接、title并支持浏览器的回退/前进按钮。

    pjax项目地址在 https://github.com/defunkt/jquery-pjax 。 实际的效果见:https://pjax.herokuapp.com/ 没有勾选pjax的时候点击链接是跳转的, 勾选了之后链接都是变成了ajax刷新(实际效果如下图的请求内容对比)。


    不使用pjax

    使用pjax
     
    优点:
    • 减轻服务端压力

      按需请求,每次只需加载页面的部分内容,而不用重复加载一些公共的资源文件和不变的页面结构,大大减小了数据请求量,以减轻对服务器的带宽和性能压力,还大大提升了页面的加载速度。

    • 优化页面跳转体验

      常规页面跳转需要重新加载画面上的内容,会有明显的闪烁,而且往往和跳转前的页面没有连贯性,用户体验不是很好。如果再遇上页面比较庞大、网速又不是很好的情况,用户体验就更加雪上加霜了。使用pjax后,由于只刷新部分页面,切换效果更加流畅,而且可以定制过度动画,在等待页面加载的时候体验就比较舒服了。

    缺点:
    • 不支持一些低版本的浏览器(如IE系列)

      pjax使用了pushState来改变地址栏的url,这是html5中history的新特性,在某些旧版浏览器中可能不支持。不过pjax会进行判断,功能不适用的时候会执行默认的页面跳转操作。

    • 使服务端处理变得复杂

      要做到普通请求返回完整页面,而pjax请求只返回部分页面,服务端就需要做一些特殊处理,当然这对于设计良好的后端框架来说,添加一些统一处理还是比较容易的,自然也没太大问题。另外,即使后台不做处理,设置pjax的fragment参数来达到同样的效果。

    综合来看,pajx的优点很强势,缺点也几乎可以忽略,还是非常值得推荐的,尤其是类似博客这种大部分情况下只有主体内容变化的网站。关键它使用简单、学习成本小,即时全站只有极个别页面能用得到,尝试下没什么损失。pjax的github主页介绍的已经很详细了,想了解更多可以看下源码。

    用法


    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失效情况
    除了上述参数外,ajax的一些参数也是可以设置在这里的,不过一般没什么必要。
    // ajax 最终参数: options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options);


    会有一些情况导致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参数

    事件


    1. 点击链接后触发的一系列事件, 除了pjax:click 和 pjax:clicked的事件源是点击的按钮,其他事件的事件源都是要替换内容的容器。可以在pjax:start事件触发时开始过度动画,在pjax:end事件触发时结束过度动画。
    事件名支持取消参数说明
    pjax:click options 点击按钮时触发。可调用e.preventDefault();取消pjax
    pjax:beforeSend xhr, options ajax执行beforeSend函数时触发,可在回调函数中设置额外的请求头参数。可调用e.preventDefault();取消pjax
    pjax:start   xhr, options pjax开始(与服务器连接建立后触发)
    pjax:send   xhr, options pjax:start之后触发
    pjax:clicked   options ajax请求开始后触发
    pjax:beforeReplace   contents, options ajax请求成功,内容替换渲染前触发
    pjax:success   data, status, xhr, options 内容替换成功后触发
    pjax:timeout xhr, options ajax请求超时后触发。可调用e.preventDefault();继续等待ajax请求结束
    pjax:error xhr, textStatus, error, options ajax请求失败后触发。默认失败后会跳转url,如要阻止跳转可调用 e.preventDefault();
    pjax:complete   xhr, textStatus, options ajax请求结束后触发,不管成功还是失败
    pjax:end   xhr, options pjax所有事件结束后触发

    注意:pjax:beforeReplace事件前pjax会调用extractContainer函数处理页面内容,即script[src]形式引入的js脚本不会被重复加载,有必要可以改下源码。

    2. 浏览器前进/后退导航时触发的事件(暂时没做过多研究)
    事件名参数说明
    pjax:popstate   页面导航方向: 'forward'/'back'(前进/后退)
    pjax:start null, options pjax开始
    pjax:beforeReplace contents, options 内容替换渲染前触发,如果缓存了要导航页面的内容则使用缓存,否则使用pjax加载
    pjax:end null, options pjax结束

    插件伴侣——NProgress


    比较漂亮的一款进度条插件,用法十分简单,很适合做pjax的过度动画,详细用法在该项目github上有介绍


    NProgress
      • 示例:$(document).on('pjax:start', NProgress.start).on('pjax:end', NProgress.done);

     示例连接:https://iathanasy.github.io/html/pjax/

    原文链接: https://www.cnblogs.com/telwanggs/p/7136716.html

  • 相关阅读:
    单例模式
    HashSet、LinkedHashSet、SortedSet、TreeSet
    ArrayList、LinkedList、CopyOnWriteArrayList
    HashMap、Hashtable、LinkedHashMap
    andrew ng machine learning week8 非监督学习
    andrew ng machine learning week7 支持向量机
    andrew ng machine learning week6 机器学习算法理论
    andrew ng machine learning week5 神经网络
    andrew ng machine learning week4 神经网络
    vue组件监听属性变化watch方法报[Vue warn]: Method "watch" has type "object" in the component definition. Did you reference the function correctly?
  • 原文地址:https://www.cnblogs.com/iathanasy/p/10956230.html
Copyright © 2011-2022 走看看