@visdoc/pjax
TypeScript icon, indicating that this package has built-in type declarations

2.1.4 • Public • Published

Pjax


@visdoc/pjax是使用ts编写的一个pjax插件,独立单文件,无任何依赖,支持过渡动画,加载动画。

安装

  npm install @visdoc/pjax

构造参数说明

  • linkSelector
    • 类型: string | (container: Element|Document) => Element|NodeList|null
    • 描述: 连接元素选择器,支持字符串选择器,也可以是一个回调函数。回调函数可返回要监听事件的元素或null,参数container在初始化时为document对象,更新容器内容时为容器元素Element对象。
    • 默认: 无
  • containerSelectors
    • 类型: string[]
    • 描述: 需要替换的元素选择器,支持任意选择器,如:['.content','div.box','#container']
    • 默认: 无
  • options 可选配置
    • options.debug
      • 类型: boolean
      • 描述: 是否开启调试模式,开启后请求加载页面失败,不会重定向
      • 默认: false
    • options.fetchOptions
      • 类型: RequestInit
      • 描述: fetch请求配置
      • 默认: {method: 'GET',headers: {Accept: 'text/html'}
    • options.behavior
      • 类型: 'smooth' | 'auto' | 'instant'
      • 描述: 页面滚动行为,默认为平滑滚动。用于滚动到锚点元素。
      • 默认: 'smooth'
    • options.topAnchors
      • 类型: string|undefined
      • 描述: 锚点元素,用于滚动到锚点元素id,无需添加#,如:top
      • 默认:undefined 滚动到页面顶部
    • options.eventDelegation
      • 类型: boolean
      • 描述: 允许事件委托,默认为true,如果为false,则只绑定当前元素,不处理子元素事件。
      • 默认:true
    • options.loadFailHandler
      • 类型: 'redirect' | 'reload' | 'none'
      • 描述: 页面加载失败时的,redirect重定向,reload强制刷新当前页面,none不处理。
      • 默认: 'redirect' 重定向到加载失败的url。
    • options.runInlineScript
      • 类型: boolean
      • 描述: 如果设置为true,则被替换的script标签中的内联脚本会被执行。
      • 默认: false
    • options.lock
      • 类型: boolean
      • 描述: 如果设置为true时,则加载过程中不会处理的新的click事件,直到加载完成。
      • 默认: false
    • options.cacheMaxLength
      • 类型: number
      • 描述: 缓存最大长度,默认为10,超过后,会删除最旧的缓存,0则不缓存。
      • 默认: 10
    • options.autoReplaceTitle
      • 类型: boolean
      • 描述: 自动替换页面标题,如果新文档存在title则替换。
      • 默认: true
    • options.logLevel
      • 类型: boolean
      • 描述: 日志等级,默认为全部日志,可选值有debug、info、warn、error
      • 默认: ['debug','info','warn','error']

教程

基本使用

import Pjax from '@visdoc/pjax'
// Pjax.isSupported() 判断是否支持window.history.pushState,不支持会使用window.location.href重定向页面
// 实例化
const pjax = new Pjax('a', ['#content'])
// 等待初始化就绪 也是在等待页面dom渲染完成
await pjax.waitReadyState()

// 更简洁的模式
await Pjax.create('a', ['#content'])

切换页面

      // 基本使用
await Pjax.factory.loadPage('/page2.html')
// 传入fetch请求头示范
await Pjax.factory.loadPage('/page2.html', { headers: { 'token': '123' } })

绑定元素

// 注意:构造函数中绑定的链接元素,在内容替换过后会自动重新绑定。
// 通过bindElement方法绑定的元素,不会在内容替换过后重新绑定,如果绑定的元素位于被替换的容器内,事件会失效。

// 某些动态渲染的元素,会导致事件失效,则可以用下面的方法重新绑定。
Pjax.factory.bindElement('a')
// 解绑
Pjax.factory.unBindElement('a')
// 为构造函数传入的选择器重新绑定事件
Pjax.factory.reset()
// 指定父容器,只会重新绑定指定容器下的元素
Pjax.factory.reset(document.querySelector('#container'))

🪝加载进度回调

pjax.onProgress = (percentage, end) => {
  console.log('当前进度:' + percentage + '%,是否结束:' + end ? '是' : '否')
}

🪝内容替换钩子

// 如果 newElement为字符串,则是回退页面时恢复页面状态的回调

// 替换内容之前的钩子
pjax.beforeReplace = async (oldElement: Element, newElement: Element | string | null) => {
  // 添加 fade-out 类,开始淡出动画
  oldElement.classList.add('fade-out');
  // 等待动画结束
  await new Promise(resolve => setTimeout(resolve, 500));
  // 移除 fade-out 类,添加 fade-in 类,开始淡入动画
  oldElement.classList.remove('fade-out');
}

// 后置的钩子,此时内容已经替换完成
pjax.afterReplace = async (oldElement: Element, newElement: Element | string | null) => {
  oldElement.classList.add('fade-in');
  // 等待动画结束
  await new Promise(resolve => setTimeout(resolve, 500)); // 0.5秒的动画时间
  // 移除 fade-in 类
  oldElement.classList.remove('fade-in');
}
// 自定义替换内容
pjax.beforeReplace = async (oldElement: Element, newElement: Element | string | null) => {
  // 没有从文档中获取到元素
  if (newElement === null) newElement = ''
  // 替换元素
  oldElement.innerHTML = typeof newElement === 'string' ? newElement : newElement.innerHTML
  return Promise.reject() // 返回Promise.reject()内部将不再执行默认的替换操作和afterReplace钩子
}

🪝页面切换回调

// 该回调仅在 window.history.pushState() 时触发,回退页面时不会触发
pjax.onSwitchPage = (oldUrl: URL, newUrl: URL) => {
  console.log('从' + oldUrl.toString() + '跳转到' + newUrl.toString())
}

状态管理

// 强制刷新页面,等同于window.location.reload()
Pjax.factory.reload(true)
// 恢复到初始加载时的状态
Pjax.factory.reload(false)
// 保存当前页面状态
Pjax.factory.saveState()
// 获取页面状态
Pjax.factory.getState()

代理点击事件

      document.getElementById('link')
  .addEventListener('click', function(e: Event) {
    // 执行自定义的逻辑....
    // 把事件交给pjax处理
    Pjax.factory.handleClickEvent.call(this, e)
  })
// 简洁写法
document.getElementById('link').addEventListener('click', Pjax.factory.handleClickEvent)

动画示例

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>进度条动画示例</title>
  <style>
    #progress-bar-container {
      pointer-events: none; /*防止用户在动画期间与内容交互*/
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 1px;
      z-index: 9999; /*确保进度条显示在所有内容之上*/
      transform: translateY(-100%);
      transition: transform .3s ease-in-out;

      #progress-bar {
        height: 100%;
        width: 0;
        transition: width 0.3s ease-in-out; /* 平滑过渡效果 */
        background-color: #4caf50; /* 进度条颜色*/
      }
    }
  </style>
</head>
<body>
<div id="progress-bar-container">
  <div id="progress-bar"></div>
</div>
<div id="doc_content"></div>
<script type="module">
  import Pjax from '@visdoc/pjax'

  const pjax = new Pjax('#nav_container', ['#doc_content'], {
    debug: true,
    strictMatchClickEvent: false
  })
  // 等待初始化就绪
  await pjax.waitReadyState()
  // 进度条容器
  const progressContainer = document.getElementById('progress-bar-container')
  // 进度条元素
  const progressBar = document.getElementById('progress-bar')
  // 利用进度钩子显示进度条
  pjax.onProgress = (progress, end) => {
    if (progressBar) {
      if (end) {
        // 如果是结束,先将进度条宽度设置为100%
        progressBar.style.width = '100%'
      } else {
        progressContainer.style.transform = 'translateY(0)'
        // 更新进度条的宽度
        progressBar.style.width = `${progress}%`
      }
    }
  }
  // 内容替换完成将进度条容器移动偏移出窗口
  pjax.afterReplace = async (oldElement) => {
    if (oldElement.id === 'doc_content') {
      // 延迟500毫秒,关闭动画
      await new Promise((resolve) => setTimeout(resolve, 500))
      progressContainer.style.transform = 'translateY(-100%)'
    }
  }
  // 模拟调用 onProgress
  setTimeout(() => pjax.onProgress(30, false), 1000); // 1秒后进度为30%
  setTimeout(() => pjax.onProgress(60, false), 2000); // 2秒后进度为60%
  setTimeout(() => pjax.onProgress(100, true), 3000); // 3秒后进度为100%,并结束
</script>
</body>
</html>

Readme

Keywords

Package Sidebar

Install

npm i @visdoc/pjax

Weekly Downloads

9

Version

2.1.4

License

MIT

Unpacked Size

70.2 kB

Total Files

6

Last publish

Collaborators

  • zhuchonglin