tpCore APIs

你可以在此页面查询最新 TypechoCore 所提供的方法。

概述

TypechoCore 是一个专为单页 Typecho 设计的小型前端支持。其能够简化动态页面附载的 JS 处理流程,同时还提供若干实用方法。常规情况下,Boinky 会自动加载此核心文件,及其能够正常工作所必需的 jQueryjQuery.pjaxjQuery Lazyload。若要编写主题脚本,则应确保所有其它文件在 tpCore 之后声明。

作为全局变量,TypechoCore 中的所有属性允许直接通过名称进行访问。它分为以下内部对象:

机读名称描述
_core父对象。作为一个引用,分配至所有子命名空间中。
xhr包含用于处理 XmlHttpRequest 行为与事件的工具函数。
engine包含用于协调基本资源与服务器响应的工具函数。
ui包含对 DOM 执行的所有操作,例如显示通知、插入元素或对话框。
storage包含用于处理 LocalStorage 的简易工具。
content这部分专为 Typecho 设计,主要目的是为了解析与后处理正文内容。

除此之外,还包含了四个基本父命名空间以允许扩展。

机读名称描述
Element用于声明、注册元素触发器函数的基本命名空间。
State用于标识、设置与读取当前页面的加载状态。
Callback在这个命名空间中直接实现回调函数,然后 tpCore 会自动在某些情况下对其进行调用处理。
Processor用于保存其它可能加载到 tpCore 中的杂项方法。

所有这些命名空间共同组织整个 tpCore。你可以根据命名空间的首字母大小写情况来判断它是一个基本空间,还是一个内部空间。通常不建议将新的通用方法或属性导入内部空间,相反,它们应该被声明至 Processor 中。至于 ElementCallback,它们均有各自的使用规范,请勿在其内部实现非必要成员。

基本模式与元素注册

随着 DOM 首次加载,tpCore 首先执行无阻塞的初始化。其中:

this.xhr.listen( this.elementInit );

它的关键任务是将 TypechoCore.elementInit 载入至 jQuery.pjax 的事件周期当中,以实现伴随页面动态加载的局部函数控制。它实际上是将前者绑定至 pjax:end 事件,该事件标志着整个 PJAX 请求与内容置换的结束;而 elementInit() 则负责处理新页面的 JavaScript。此函数实现逻辑:

  • 查找所有携带 data-typecho-init 属性的元素。对于每个元素...
  • 查询该元素的 dataset.initialized。若其为 true,则跳过;否则...
  • 获取此 data-typecho-init 属性值,并查询其是否已被 triggerElement() 显式绑定于 TypechoCore.initRegistry
  • 获取此属性值作为键名在 initRegistry 中的映射名,然后执行此映射名函数。携带此 typecho-init 属性的元素作为唯一形参。
  • 将此元素的 dataset.initialized 标记为 true,以规避下一次轮询。

上述流程执行于每次页面加载完毕。TypechoCore 依此实现 PJAX 下的 JavaScript 控制。

将元素注册至 initRegistry

根命名空间提供方法 registerElement() 以允许向任意 DOM 元素注册动态脚本。

registerElement: function(initTrigger, alias = null, triggerOnRegister = true)
  • initTrigger 是目标元素的 data-typecho-init 属性值字符串。
  • 参数 alias 为可选别名。该别名未提供或为 null 时,tpCore 将自动使用 initTrigger 的驼峰格式作为目标映射函数的名称。
  • 参数 triggerOnRegister 为声明控制。若此参数为 true,则在调用 registerElementtpCore 执行注册时,会自动触发一次针对目标元素的 elementInit

若如此做,则下次 PJAX 请求获取目标页面时,若携带 data-typecho-init 属性值为 initTrigger 的元素存在于目标页,则下方的函数会被执行:

TypechoCore.Element.INIT_REGISTRY_NAME()

其中 INIT_REGISTRY_NAME 是目标映射函数的别名。它必须位于 Element 命名空间,且其名称符合下列情况之一:

  1. 若未在 registerElement 中提供参数 alias 或其为 null,则必须严格为 initTrigger 字符串值的驼峰写法。如:test-function => testFunction
  2. 若传入字符串 alias,则应与 alias 一致。如:test_alias_function => test_alias_function

最终一个符合上述命名要求且与元素触发标识 initTrigger 绑定的映射将被记录至属性 TypechoCore.initRegistry。下面是一个完整的示例:

TypechoCore.Element.testFunction = function( $element ) {
	const className = $element.attr( 'class' );

	console.log( 'The class name of trigger element is: ' + className );
	console.log( 'This is a test element-based function!' );
}
TypechoCore.registerElement('test-function');
<div class="some-class" data-typecho-init="test-function"></div>

载入携带目标 HTML 的页面,则控制台将会显示相应内容。最后,使用下面的函数来判断目标(原始)名称是否已注册至 initRegistry

TypechoCore.isElementRegistered( 'test-function' );

事件创建与销毁

在切换页面的整个过程中,我们经常需要创建事件、解绑事件,以及插入或销毁元素。实际上它们都是基于 PJAX 的。TypechoCore 提供的 xhr 集提供了若干简单的方法,它们可以帮助略微简化上述操作。将来版本的 tpCore 可能会支持更加复杂的行为。要声明 PJAX 事件监听器,使用:

TypechoCore.xhr.listen( callback, executeAtOnce = false, eventName = 'end' );

此代码将函数 callback 永久绑定至 pjax:eventName 事件。参数 executeAtOnce 控制目标函数是否在执行此绑定操作之后立刻执行一次。

很多情况下我们只希望在下次而非永久请求页面的时候执行某些操作,比如销毁特定的元素或对象。要如此做,则使用:

TypechoCore.xhr.listenOnce( callback, eventName = 'beforeReplace' );

这等价于 $(document).one('pjax:eventName', callback)。查阅 PJAX 文档以了解所有 PJAX 事件的名称及详细信息。请注意:显然,被绑定的函数不会拥有上下文,这意味着目标函数中不应包含任何 this 或与之类似的调用。最后,xhr 空间还提供了对两个 jQuery 原生方法的借用:

TypechoCore.xhr.makeRequset();			// 等价 $.ajax
TypechoCore.xhr.makePopStateRequest();	// 等价 $.pjax

资源的动态请求

有时候我们只想让目标功能在被使用的时候,浏览器才会加载其脚本与样式表文件——若用户并未用到这些功能,则不会加载以节省资源。比如 Citizen 中随处可见的富文本编辑器。它的依赖文件大小高达 1MB,不加判断地直接引用这些依赖,显然会影响到用户的浏览体验。TypechoCore 允许函数以异步方式尝试获取这些文件。

const loadFancybox = async function() {
	await TypechoCore.engine.requestResource( 'https://.../jquery.fancybox.min.js' );
	...
}

上面的函数将会等待目标文件 jquery.fancybox.min.js 完全加载到本地,然后再执行之后的操作。当然,也可以使用等待链,以及一次性传入多个资源:

TypechoCore.engine.requestResource( [
	'https://.../jquery.fancybox.min.js',
	'https://.../jquery.fancybox.min.css'
] ).then( ... );

它的原理是通过 $.getScript 获取 JS;通过 $('head').append 获取 CSS。在 TypechoCore.engine 内部,此方法事实上是与名为 requestNew 的方法协同工作,后者负责将资源的文件名保存至 TypechoCore.resolvedRequests 中,然后检查与处理后续可能存在的重复请求项。使用下面的代码来判断指定资源是否已被请求:

TypechoCore.engine.isResolved( 'jquery.fancybox.min.js' );

无论何种情况,当 requestResource 开始准备请求资源时,触发 core:promisedLoadStart 事件;所有请求结束时,触发 core:promisedLoadEnd 事件。

添加新评论

点击评论者的头像,即可对其进行回复。

    叶开
    叶开 qq.md 7 月 18 日

    categories 分类页面 没有内容撑起, 页面滚动 底部就会出现空白了. 文章页面又内容撑起 不会

    Saammaa
    Saammaa 回复 @叶开 | 7 月 18 日

    OK 等俺有空修复这个小小的问题

    叶开
    叶开 qq.md 7 月 18 日

    很强!