LogoLogo
  • README
  • 前端编程
    • 01 Node JS
    • 02-ES6详解
    • 03-NPM详解
    • 04-Babel详解
    • 05-前端模块化开发
    • 06-WebPack详解
    • 07-Vue详解
    • 08-Git详解
    • 09-微信小程序
  • 人工智能
    • 机器学习
      • 二次分配问题
      • 非负矩阵
      • 概率潜在语义分析
      • 概率图模型
      • 集成学习
      • 降维
      • 距离度量
      • 决策树
      • 逻辑回归
      • 马尔可夫决策过程
      • 马尔可夫链蒙特卡洛法
      • 朴素贝叶斯法
      • 谱聚类
      • 奇异值分解
      • 潜在狄利克雷分配
      • 潜在语义分析
      • 强化学习
      • 社区算法
      • 时间序列模型
      • 特征工程
      • 条件随机场
      • 图论基础
      • 线性分类
      • 线性回归
      • 信息论中的熵
      • 隐马尔科夫模型
      • 支持向量机
      • 主成分分析
      • EM算法
      • Hermite 矩阵的特征值不等式
      • k-means聚类
      • k近邻法
      • PageRank算法
    • 深度学习
      • Pytorch篇
        • 01-线性模型
        • 02-梯度下降法
        • 03-反向传播
        • 04-pytorch入门
        • 05-用pytorch实现线性回归
        • 06-logistic回归
        • 07-处理多维特征的输入
        • 08-加载数据集
        • 09-多分类问题
        • 10-卷积神经网络
        • 11-循环神经网络
    • 图神经网络
      • 图神经网络笔记01
        • 01-图(Graphs)的结构
        • 02-网络的性质和随机图模型
        • 03-网络工具
        • 04-网络中的主题和结构角色
        • 05-网络中的社区结构
      • 图神经网络笔记02
        • 01-深度学习引言
        • 02-神经网络基础
        • 03-卷积神经网络
        • 04-图信号处理与图卷积神经网络
        • 05-GNN的变体与框架-
        • [06-Google PPRGo 两分钟分类千万节点的最快GNN](人工智能/图神经网络/图神经网络笔记02/06-Google%20PPRGo 两分钟分类千万节点的最快GNN.md)
        • 07-序列模型
        • 08-变分自编码器
        • 09-对抗生成网络
  • 日常记录
    • 健身日记
    • 面经记录
    • 自动生成Summary文件
  • 实战项目
    • 谷粒商城
      • 00-项目概述
      • 01-分布式基础-全栈开发篇
      • 02-分布式高级-微服务架构篇
      • 03-高可用集群-架构师提升篇
  • 数据库
    • MySQL笔记
      • 01-MySQL基础篇
      • 02-MySQL架构篇
      • 03-MySQL索引及调优篇
      • 04-MySQL事务篇
      • 05-MySQL日志与备份篇
    • Redis笔记
      • 01-Redis基础篇
      • 02-Redis高级篇
    • 02-Redis篇
  • 算法笔记
    • 01-算法基础篇
    • 02-算法刷题篇
  • 职能扩展
    • 产品运营篇
  • Go编程
    • 01-Go基础
      • 01-Go基础篇
  • Java编程
    • 01-Java基础
      • 01-Java基础篇
      • 02-多线程篇
      • 03-注射与反解篇
      • 04-JUC并发编程篇
      • 05-JUC并发编程与源码分析
      • 06-JVM原理篇
      • 07-Netty原理篇
      • 08-设计模式篇
    • 02 Java Web
      • 01-Mybatis篇
      • 01-Mybatis篇(新版)
      • 02-Spring篇
      • 02-Spring篇(新版)
      • 03-SpringMVC篇
      • 04-MybatisPlus篇
    • 03-Java微服务
      • 01-SpringBoot篇
      • 01-SpringBoot篇(新版)
      • 02-SpringSecurity篇
      • 03-Shiro篇
      • 04-Swagger篇
      • 05-Zookeeper篇
      • 06-Dubbo篇
      • 07-SpringCloud篇
      • 08-SpringAlibaba篇
      • 09-SpringCloud篇(新版)
    • 04-Java中间件
      • 数据库篇
        • 01-分库分表概述
        • 02-MyCat篇
        • 03-MyCat2篇
        • 04-Sharding-jdbc篇
        • 05-ElasticSearch篇
      • 消息中间件篇
        • 01-MQ概述
        • 02-RabbitMQ篇
        • 03-Kafka篇
        • 04-RocketMQ篇
        • 05-Pulsar篇
    • 05-扩展篇
      • Dubbo篇
      • SpringBoot篇
      • SpringCloud篇
    • 06-第三方技术
      • 01-CDN技术篇
      • 02-POI技术篇
      • 03-第三方支付技术篇
      • 04-第三方登录技术篇
      • 05-第三方短信接入篇
      • 06-视频点播技术篇
      • 07-视频直播技术篇
    • 07-云原生
      • 01-Docker篇
      • 02-Kubernetes篇
      • 03-Kubesphere篇
  • Linux运维
    • 01-Linux篇
    • 02-Nginx篇
  • Python编程
    • 01-Python基础
      • 01.配置环境
      • 02.流程控制
      • 03.数值
      • 04.操作符
      • 05.列表
      • 06.元祖
      • 07.集合
      • 08.字典
      • 09.复制
      • 10.字符串
      • 11.函数
      • 12.常见内置函数
      • 13.变量
      • 14.异常和语法错误
      • 15.时间和日期
      • 16.正则表达式
    • 02 Python Web
      • flask篇
        • 01.前言
        • 02.路由
        • 03.模板
        • 04.视图进阶
        • 05.flask-sqlalchemy
        • 06.表单WTForms
        • 07.session与cookie
        • 08.上下文
        • 09.钩子函数
        • 10.flask 信号
        • 11.RESTFUL
        • 13.flask-mail
        • 14.flask+celery
        • 15.部署
        • 16.flask-login
        • 17.flask-cache
        • 18.flask-babel
        • 19.flask-dashed
        • 20.flask-pjax
        • 21.flask上传文件到第三方
        • 22.flask-restless
        • 23.flask-redis
        • 24.flask-flash
        • 25.消息通知
        • 26.分页
    • 03-Python数据分析
      • Matplotlib
      • Numpy
      • Pandas
      • Seaborn
    • 04-Python爬虫
      • 1.准备工作
      • 2.请求模块的使用
      • 3.解析模块的使用
      • 4.数据存储
      • 5.识别验证码
      • 6.爬取APP
      • 7.爬虫框架
      • 8.分布式爬虫
由 GitBook 提供支持
在本页
  • 概念
  • 什么是Pjax?
  • Pjax有什么用?
  • 为什么要用Pjax?
  • 安装
  • 配置与用法

这有帮助吗?

在GitHub上编辑
  1. Python编程
  2. 02 Python Web
  3. flask篇

20.flask-pjax

上一页19.flask-dashed下一页21.flask上传文件到第三方

最后更新于3年前

这有帮助吗?

概念

什么是Pjax?

Pjax = history.pushState + Ajax
     = history.pushState + Async JS + XML(xhr?)

BOM对象history被增强了一波,主要是对历史栈的操作,以前只有replace, go之类的,都会跳转并刷新整个页面,现在有了pushState, replaceState等等单纯操作历史栈的方法,只是单纯修改历史栈里的内容,没有副作用(页面不会跳转刷新)

关于history对象的更多信息请查看

Pjax有什么用?

1.最初的单页面应用(SPA)

页面刷新不仅浪费资源(很多同级页面上大部分内容都是相同的,没必要重新加载这些重复内容),还影响用户体验(loadingloadingloading…)。局部刷新能够避免loading影响用户体验,从Ajax概念一出来就有人开始这么做了,把整站做成单页面应用(Single Page App,简称SPA),Ajax请求JSON,再局部刷新呈现数据,最初的SPA存在很多缺点:

  • 最大的问题:页面内容与URL不对应。

    这是致命的缺点,用户看到的内容与地址栏URL不对应,意味着内容无法分享传播(分享传播太重要了),浏览器前进/后退按钮也无法按照用户预期工作。

  • 其次:破坏SEO。

    纯Ajax实现的SPA对SEO有极大的消极影响,由于页面上很多内容都是Ajax请求之后js控制呈现的,蜘蛛看不到这些内容,也就根本不会被索引/收录。

2.pretty AJAX URL

为了解决SEO问题,Google提出了一种很丑(虽然名字叫pretty AJAX URL。。)的方法:#!

据说Twitter用过一个月,后来用户反馈说太丑了,再后来就不用了。这种很丑的url确实能解决上述的第2个问题,但是需要搜索引擎配合,Google认可这种方式,Google的蜘蛛会把mydomain.com/index.html#!article1和mydomain.com/index.html#!article2当作两个不同的页面对待,服务给这种特殊URL的请求返回对应的页面即可,SEO问题没了。

但第一个问题还在,页面内容与URL仍然不对应,于是有了下面要说的Pjax。

3.Pjax

W3C提出了新的API,增强了history对历史栈的控制能力,能够直接修改地址栏URL,直到这时页面内容与URL才终于能够对应了。

每次局部刷新成功之后都调用history.pushState同步更新地址栏的URL(维护历史栈),这些URL都对应可以直接访问的页面,每个局部刷新动作都是由a标签触发的,js拦截默认跳转,再Ajax请求数据呈现数据,用户看到的是局部刷新和流畅的体验,蜘蛛看到的是普通的a标签页面跳转,页面展示的内容始终与直接访问URL得到的内容一致,致命缺点也不存在了。

为什么要用Pjax?

在不影响SEO的前提下,局部刷新 + 本地缓存能够带来前所未有的快速体验,这是Pjax的绝对优势。

Pjax适用于非纯移动端的单页面应用,能够实现流畅的用户体验,而且封装好的Pjax组件支持一些额外的功能,比如缓存、本地存储、动画等等,使用起来也很方便。

移动页面一般不存在频繁地大篇幅页面内容更新,而且移动页面很少需要考虑SEO,直接用Ajax即可。

安装

pip install flask-pjax

配置与用法

导入flask_pjax,创建实例化对象,并进行初始化。

from flask import Flask,render_template
from flask_pjax import PJAX

app = Flask(__name__)
pjax = PJAX()
pjax.init_app(app)

@app.route('/')
def index():
    return "Hello World"

if __name__ == "__main__":
    app.run()

设置基本模板

PJAX_BASE_TEMPLATE = "pjax.html"

创建base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本模板</title>
</head>
<body>

<div data-gb-custom-block data-tag="block">

</div>

</body>
</html>

创建pjax.html

<div data-gb-custom-block data-tag="block"> </div>

创建index.html

<div data-gb-custom-block data-tag="extends" data-0='base.html'></div>

<div data-gb-custom-block data-tag="block">

<div class="container">
    <p style="color: white;text-align: center">Welcome to the Index page.</p>
</div>

</div>

创建A.html、B.html、C.html

<div data-gb-custom-block data-tag="extends" data-0='base.html'></div>

<div data-gb-custom-block data-tag="block">

<div class="container">
  <p style="color: white;text-align: center">The A page.</p>
</div>

</div>
...
<div class="container">
  <p style="color: white;text-align: center">The B page.</p>
</div>
....
...
<div class="container">
  <p style="color: white;text-align: center">The C page.</p>
</div>
...

创建app.py

"""Testing Flask with PJAX."""
from flask import Flask, request, render_template
from flask_pjax import PJAX

app = Flask(__name__)
app.config["PJAX_BASE_TEMPLATE"] = "pjax.html"

pjax = PJAX()
pjax.init_app(app)


@app.route('/')
def home():
    return render_template('index.html')

@app.route('/A')
def a_pjax():
    return render_template('A.html')

@app.route('/B')
def b_pjax():
    return render_template('B.html')

@app.route('/C')
def c_pjax():
    return render_template('C.html')

if __name__ == '__main__':
    app.run()

这将为PJAX请求呈现pjax.html,为非PJAX请求呈现基础。

另外指定自定义PJAX基本模板:

<div data-gb-custom-block data-tag="extends" data-0='base.html' data-1=', pjax=' data-ax='/base/custom_pjax_template'></div>

如果各个良好的话,Pjax能够完美支持单页面应用,如果浏览器不支持新API就把它当蜘蛛好了(目前好像没有好用的兼容方案,也无能为力),至于css/js冲突、内存泄露等等都是SPA本身的问题,成熟的SPA方案应该可以避免这些问题。

MDN History
浏览器支持性
jq插件