wp-javascript

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

WordPress JavaScript & AJAX

WordPress中的JavaScript与AJAX

Reference for JavaScript integration in WordPress: script registration and enqueuing, passing data from PHP to JS, AJAX request/response patterns, the Heartbeat API, jQuery usage, and loading strategies.

本指南是WordPress中JavaScript集成的参考手册:包含脚本注册与入队、PHP向JavaScript传递数据、AJAX请求/响应模式、Heartbeat API、jQuery使用方法以及加载策略。

1. Enqueuing Scripts

1. 脚本入队

WordPress manages JavaScript dependencies through a registration and enqueuing system. Never output
<script>
tags directly — always use the enqueue API.
WordPress通过注册和入队系统管理JavaScript依赖。切勿直接输出
<script>
标签——务必使用入队API。

Basic Pattern

基础模式

php
add_action( 'wp_enqueue_scripts', 'map_enqueue_frontend_scripts' );

function map_enqueue_frontend_scripts(): void {
    wp_enqueue_script(
        'map-frontend',                                // Handle (unique identifier).
        plugins_url( 'assets/js/frontend.js', __FILE__ ), // Full URL to file.
        array( 'jquery' ),                             // Dependencies.
        '1.0.0',                                       // Version (cache busting).
        array( 'in_footer' => true )                   // Load in footer.
    );
}
php
add_action( 'wp_enqueue_scripts', 'map_enqueue_frontend_scripts' );

function map_enqueue_frontend_scripts(): void {
    wp_enqueue_script(
        'map-frontend',                                // 句柄(唯一标识符)。
        plugins_url( 'assets/js/frontend.js', __FILE__ ), // 文件完整URL。
        array( 'jquery' ),                             // 依赖项。
        '1.0.0',                                       // 版本号(用于缓存刷新)。
        array( 'in_footer' => true )                   // 在页脚加载。
    );
}

Enqueue Hooks

入队钩子

HookWhere Scripts LoadCallback Parameter
wp_enqueue_scripts
Frontend pagesNone
admin_enqueue_scripts
Admin pages
$hook_suffix
(page filename)
login_enqueue_scripts
Login pageNone
钩子名称脚本加载位置回调函数参数
wp_enqueue_scripts
前端页面
admin_enqueue_scripts
后台管理页面
$hook_suffix
(页面文件名)
login_enqueue_scripts
登录页面

Conditional Loading (Admin)

条件加载(后台)

Load scripts only on your plugin's admin page — not on every admin screen:
php
add_action( 'admin_enqueue_scripts', 'map_enqueue_admin_scripts' );

function map_enqueue_admin_scripts( string $hook_suffix ): void {
    // $hook_suffix examples: 'toplevel_page_my-plugin', 'settings_page_my-plugin-settings'.
    if ( 'toplevel_page_my-plugin' !== $hook_suffix ) {
        return;
    }

    wp_enqueue_script(
        'map-admin',
        plugins_url( 'assets/js/admin.js', __FILE__ ),
        array( 'jquery', 'wp-util' ),
        MAP_VERSION,
        array( 'in_footer' => true )
    );
}
仅在你的插件后台页面加载脚本——不要在所有后台界面都加载:
php
add_action( 'admin_enqueue_scripts', 'map_enqueue_admin_scripts' );

function map_enqueue_admin_scripts( string $hook_suffix ): void {
    // $hook_suffix示例:'toplevel_page_my-plugin', 'settings_page_my-plugin-settings'.
    if ( 'toplevel_page_my-plugin' !== $hook_suffix ) {
        return;
    }

    wp_enqueue_script(
        'map-admin',
        plugins_url( 'assets/js/admin.js', __FILE__ ),
        array( 'jquery', 'wp-util' ),
        MAP_VERSION,
        array( 'in_footer' => true )
    );
}

Conditional Loading (Frontend)

条件加载(前端)

php
add_action( 'wp_enqueue_scripts', 'map_enqueue_conditionally' );

function map_enqueue_conditionally(): void {
    // Only load on single posts.
    if ( ! is_single() ) {
        return;
    }

    wp_enqueue_script( 'map-single', /* ... */ );
}
php
add_action( 'wp_enqueue_scripts', 'map_enqueue_conditionally' );

function map_enqueue_conditionally(): void {
    // 仅在单篇文章页面加载。
    if ( ! is_single() ) {
        return;
    }

    wp_enqueue_script( 'map-single', /* ... */ );
}

Register vs Enqueue

注册 vs 入队

php
// Register (makes handle available, doesn't load yet).
wp_register_script( 'map-charts', plugins_url( 'assets/js/charts.js', __FILE__ ), array(), '2.0.0', true );

// Enqueue later when needed (e.g., inside a shortcode callback).
function map_chart_shortcode( $atts ): string {
    wp_enqueue_script( 'map-charts' );  // Now it loads.
    return '<div id="map-chart"></div>';
}
Registration is useful when a script should only load conditionally (inside a shortcode, meta box, or specific template).

php
// 注册(使句柄可用,但暂不加载)。
wp_register_script( 'map-charts', plugins_url( 'assets/js/charts.js', __FILE__ ), array(), '2.0.0', true );

// 在需要时再入队(例如,在短代码回调函数中)。
function map_chart_shortcode( $atts ): string {
    wp_enqueue_script( 'map-charts' );  // 此时脚本才会加载。
    return '<div id="map-chart"></div>';
}
注册适用于仅在特定条件下才需要加载的脚本(例如,短代码、元框或特定模板内)。

2. Passing Data from PHP to JavaScript

2. 从PHP向JavaScript传递数据

wp_localize_script()

wp_localize_script()

Passes PHP values to JavaScript as a global object. Must be called after the script is enqueued/registered and before
wp_head()
/
wp_footer()
fires.
php
wp_enqueue_script( 'map-ajax', plugins_url( 'assets/js/ajax.js', __FILE__ ), array( 'jquery' ), '1.0.0', true );

wp_localize_script( 'map-ajax', 'mapAjax', array(
    'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    'nonce'   => wp_create_nonce( 'map_ajax_nonce' ),
    'homeUrl' => home_url( '/' ),
    'i18n'    => array(
        'loading' => __( 'Loading...', 'my-plugin' ),
        'error'   => __( 'An error occurred.', 'my-plugin' ),
    ),
) );
In JavaScript, the data is available as a global:
js
console.log( mapAjax.ajaxUrl );  // "https://example.com/wp-admin/admin-ajax.php"
console.log( mapAjax.nonce );    // "a1b2c3d4e5"
console.log( mapAjax.i18n.loading ); // "Loading..."
Limitations:
  • All values are cast to strings (numbers become
    "5"
    , booleans become
    ""
    or
    "1"
    ).
  • For complex data, use
    wp_add_inline_script()
    with
    wp_json_encode()
    instead.
将PHP值作为全局对象传递给JavaScript。必须在脚本入队/注册之后、
wp_head()
/
wp_footer()
触发之前调用。
php
wp_enqueue_script( 'map-ajax', plugins_url( 'assets/js/ajax.js', __FILE__ ), array( 'jquery' ), '1.0.0', true );

wp_localize_script( 'map-ajax', 'mapAjax', array(
    'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    'nonce'   => wp_create_nonce( 'map_ajax_nonce' ),
    'homeUrl' => home_url( '/' ),
    'i18n'    => array(
        'loading' => __( 'Loading...', 'my-plugin' ),
        'error'   => __( 'An error occurred.', 'my-plugin' ),
    ),
) );
在JavaScript中,数据可通过全局对象访问:
js
console.log( mapAjax.ajaxUrl );  // "https://example.com/wp-admin/admin-ajax.php"
console.log( mapAjax.nonce );    // "a1b2c3d4e5"
console.log( mapAjax.i18n.loading ); // "Loading..."
局限性:
  • 所有值都会被转换为字符串(数字变为
    "5"
    ,布尔值变为
    ""
    "1"
    )。
  • 对于复杂数据,请使用
    wp_add_inline_script()
    配合
    wp_json_encode()
    替代。

wp_add_inline_script()

wp_add_inline_script()

Injects a
<script>
block tied to a registered handle. Supports
'before'
or
'after'
positioning (default:
'after'
).
php
wp_enqueue_script( 'map-app', plugins_url( 'assets/js/app.js', __FILE__ ), array(), '1.0.0', true );

wp_add_inline_script( 'map-app', sprintf(
    'var mapConfig = %s;',
    wp_json_encode( array(
        'apiBase'    => rest_url( 'map/v1/' ),
        'nonce'      => wp_create_nonce( 'wp_rest' ),
        'maxItems'   => 50,        // Stays as integer.
        'debug'      => WP_DEBUG,  // Stays as boolean.
    ) )
), 'before' );
Use
'before'
when your main script needs the config variable at load time.
注入与已注册句柄关联的
<script>
块。支持
'before'
'after'
位置(默认:
'after'
)。
php
wp_enqueue_script( 'map-app', plugins_url( 'assets/js/app.js', __FILE__ ), array(), '1.0.0', true );

wp_add_inline_script( 'map-app', sprintf(
    'var mapConfig = %s;',
    wp_json_encode( array(
        'apiBase'    => rest_url( 'map/v1/' ),
        'nonce'      => wp_create_nonce( 'wp_rest' ),
        'maxItems'   => 50,        // 保持为整数类型。
        'debug'      => WP_DEBUG,  // 保持为布尔类型。
    ) )
), 'before' );
当主脚本在加载时需要配置变量时,使用
'before'
位置。

Script Translation (i18n)

脚本国际化(i18n)

For Block Editor scripts using
wp.i18n.__()
:
php
wp_set_script_translations( 'map-editor', 'my-plugin', plugin_dir_path( __FILE__ ) . 'languages' );

对于使用
wp.i18n.__()
的区块编辑器脚本:
php
wp_set_script_translations( 'map-editor', 'my-plugin', plugin_dir_path( __FILE__ ) . 'languages' );

3. Script Dependencies & Built-in Libraries

3. 脚本依赖与内置库

Common WordPress Script Handles

常见WordPress脚本句柄

HandleLibraryNotes
jquery
jQuery (latest bundled)Runs in noConflict mode
jquery-core
jQuery core without migrateLighter, no deprecated API shims
wp-api-fetch
@wordpress/api-fetch
REST API requests with nonce
wp-element
@wordpress/element
(React wrapper)
Block Editor components
wp-data
@wordpress/data
Block Editor state management
wp-hooks
@wordpress/hooks
JS action/filter system
wp-i18n
@wordpress/i18n
__()
,
_n()
for JS
wp-util
wp.ajax
,
wp.template
AJAX helpers, Underscore templates
underscore
Underscore.jsUtility library
backbone
Backbone.jsMV* framework
wp-mediaelement
MediaElement.jsAudio/video player
thickbox
ThickBoxModal dialogs
句柄名称库名称说明
jquery
jQuery(最新捆绑版本)以noConflict模式运行
jquery-core
不含migrate的jQuery核心更轻量,无已弃用API的兼容层
wp-api-fetch
@wordpress/api-fetch
带nonce的REST API请求
wp-element
@wordpress/element
(React包装器)
区块编辑器组件
wp-data
@wordpress/data
区块编辑器状态管理
wp-hooks
@wordpress/hooks
JavaScript动作/过滤器系统
wp-i18n
@wordpress/i18n
JS中的
__()
_n()
函数
wp-util
wp.ajax
,
wp.template
AJAX辅助工具、Underscore模板
underscore
Underscore.js实用工具库
backbone
Backbone.jsMV*框架
wp-mediaelement
MediaElement.js音视频播放器
thickbox
ThickBox模态对话框

jQuery in WordPress

WordPress中的jQuery

WordPress loads jQuery in noConflict mode — the
$
shortcut is not available globally.
js
// WRONG — $ is undefined in noConflict mode.
$( '.my-element' ).hide();

// Option 1: Use the full name.
jQuery( '.my-element' ).hide();

// Option 2: Wrap in an IIFE (recommended).
( function( $ ) {
    $( '.my-element' ).hide();
    $( document ).ready( function() {
        // DOM ready code.
    } );
} )( jQuery );

// Option 3: jQuery ready shorthand.
jQuery( function( $ ) {
    $( '.my-element' ).hide();
} );
WordPress以noConflict模式加载jQuery——全局环境中无法使用
$
快捷方式。
js
// 错误写法——noConflict模式下$未定义。
$( '.my-element' ).hide();

// 选项1:使用完整名称。
jQuery( '.my-element' ).hide();

// 选项2:包裹在立即执行函数表达式中(推荐)。
( function( $ ) {
    $( '.my-element' ).hide();
    $( document ).ready( function() {
        // DOM加载完成后的代码。
    } );
} )( jQuery );

// 选项3:jQuery ready快捷写法。
jQuery( function( $ ) {
    $( '.my-element' ).hide();
} );

Loading Strategies (WordPress 6.3+)

加载策略(WordPress 6.3+)

StrategyBehavior
defer
Script executes after DOM is constructed, in order
async
Script executes immediately when downloaded, no order
(default)Blocking — halts parsing until script runs
php
wp_enqueue_script( 'map-analytics', plugins_url( 'assets/js/analytics.js', __FILE__ ), array(), '1.0.0', array(
    'in_footer' => true,
    'strategy'  => 'defer',   // Non-blocking, ordered execution.
) );
WordPress automatically adjusts strategies to prevent dependency conflicts. If a dependency uses blocking, the dependent script cannot use
async
.

策略行为
defer
脚本在DOM构建完成后按顺序执行
async
脚本下载完成后立即执行,不保证顺序
默认阻塞式——在脚本运行前暂停页面解析
php
wp_enqueue_script( 'map-analytics', plugins_url( 'assets/js/analytics.js', __FILE__ ), array(), '1.0.0', array(
    'in_footer' => true,
    'strategy'  => 'defer',   // 非阻塞,按顺序执行。
) );
WordPress会自动调整策略以避免依赖冲突。如果某个依赖项使用阻塞式加载,那么依赖它的脚本无法使用
async
策略。

4. AJAX

4. AJAX

WordPress routes all AJAX requests through
wp-admin/admin-ajax.php
. The standard pattern: register
wp_ajax_{action}
(and optionally
wp_ajax_nopriv_{action}
) hooks, verify the nonce with
check_ajax_referer()
, sanitize input, process data, and return a JSON response via
wp_send_json_success()
or
wp_send_json_error()
. On the client side, use
jQuery.post()
with the localized AJAX URL and action name.
<!-- Full PHP handler and jQuery client examples: resources/ajax-patterns.md -->
WordPress将所有AJAX请求路由到
wp-admin/admin-ajax.php
。标准流程:注册
wp_ajax_{action}
(可选
wp_ajax_nopriv_{action}
)钩子,使用
check_ajax_referer()
验证nonce,清理输入数据,处理业务逻辑,然后通过
wp_send_json_success()
wp_send_json_error()
返回JSON响应。在客户端,使用
jQuery.post()
配合本地化的AJAX URL和动作名称。
<!-- 完整的PHP处理程序和jQuery客户端示例:resources/ajax-patterns.md -->

Response Functions

响应函数

FunctionUse Case
wp_send_json_success( $data )
{ success: true, data: $data }
wp_send_json_error( $data )
{ success: false, data: $data }
wp_send_json( $data )
Raw JSON (no success wrapper)
All three call
wp_die()
internally — do not
echo
or
exit
after them.
函数名称使用场景
wp_send_json_success( $data )
返回
{ success: true, data: $data }
wp_send_json_error( $data )
返回
{ success: false, data: $data }
wp_send_json( $data )
返回原始JSON(无success包装)
这三个函数都会在内部调用
wp_die()
——调用后不要使用
echo
exit

Nonce Verification

Nonce验证

FunctionUse Case
check_ajax_referer( $action, $key )
Dies on failure (use for AJAX handlers)
wp_verify_nonce( $_POST['nonce'], $action )
Returns false on failure (manual check)
函数名称使用场景
check_ajax_referer( $action, $key )
验证失败时终止程序(用于AJAX处理程序)
wp_verify_nonce( $_POST['nonce'], $action )
验证失败时返回false(手动检查)

Admin-Only vs Public AJAX

仅后台 vs 公开AJAX

Hook PatternWho Can Call
wp_ajax_{action}
Logged-in users only
wp_ajax_nopriv_{action}
Non-logged-in users only
Both hooks registeredAll users
Register
nopriv
only if the endpoint must work for anonymous visitors. Always verify a nonce even on logged-in-only endpoints.

钩子模式可调用用户群体
wp_ajax_{action}
仅已登录用户
wp_ajax_nopriv_{action}
仅未登录用户
同时注册两个钩子所有用户
仅当端点需要对匿名访客开放时,才注册
nopriv
钩子。即使是仅对已登录用户开放的端点,也务必验证nonce。

5. Fetch API & wp.apiFetch (Modern Alternative)

5. Fetch API & wp.apiFetch(现代替代方案)

For modern JavaScript (no jQuery dependency), use
wp.apiFetch
or the native Fetch API with the WordPress REST API instead of admin-ajax.php.
对于现代JavaScript(无jQuery依赖),请使用
wp.apiFetch
或原生Fetch API配合WordPress REST API,替代admin-ajax.php。

wp.apiFetch

wp.apiFetch

js
// Automatically includes X-WP-Nonce header.
wp.apiFetch( { path: '/wp/v2/posts?per_page=5' } )
    .then( function( posts ) {
        console.log( posts );
    } );

// POST request.
wp.apiFetch( {
    path: '/map/v1/settings',
    method: 'POST',
    data: { key: 'value' },
} ).then( function( response ) {
    console.log( response );
} );
Requires
wp-api-fetch
as a dependency:
php
wp_enqueue_script( 'map-modern', plugins_url( 'assets/js/modern.js', __FILE__ ), array( 'wp-api-fetch' ), '1.0.0', true );
js
// 自动包含X-WP-Nonce请求头。
wp.apiFetch( { path: '/wp/v2/posts?per_page=5' } )
    .then( function( posts ) {
        console.log( posts );
    } );

// POST请求。
wp.apiFetch( {
    path: '/map/v1/settings',
    method: 'POST',
    data: { key: 'value' },
} ).then( function( response ) {
    console.log( response );
} );
需要将
wp-api-fetch
作为依赖项:
php
wp_enqueue_script( 'map-modern', plugins_url( 'assets/js/modern.js', __FILE__ ), array( 'wp-api-fetch' ), '1.0.0', true );

Native Fetch with REST API

原生Fetch配合REST API

js
fetch( mapConfig.apiBase + 'settings', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-WP-Nonce': mapConfig.nonce,
    },
    body: JSON.stringify( { key: 'value' } ),
} )
.then( r => r.json() )
.then( data => console.log( data ) );
js
fetch( mapConfig.apiBase + 'settings', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-WP-Nonce': mapConfig.nonce,
    },
    body: JSON.stringify( { key: 'value' } ),
} )
.then( r => r.json() )
.then( data => console.log( data ) );

When to Use What

方案选择

ApproachBest For
admin-ajax.phpLegacy code, simple form submissions, no REST API
wp.apiFetch
Block Editor scripts, admin React UI
Native Fetch + RESTHeadless/decoupled, modern JS, custom REST routes

方案最佳适用场景
admin-ajax.php遗留代码、简单表单提交、无REST API的场景
wp.apiFetch
区块编辑器脚本、后台React界面
原生Fetch + REST API无头/解耦架构、现代JS、自定义REST路由

6. Heartbeat API

6. Heartbeat API

The Heartbeat API provides near-real-time server polling. WordPress uses it for post locking, autosave, and login session management.
Heartbeat API提供近实时的服务器轮询功能。WordPress将其用于文章锁定、自动保存和登录会话管理。

How It Works

工作原理

  1. Browser fires a "tick" every 15-120 seconds (default: 60s on most pages, 15s on post editor).
  2. Client-side code attaches data via
    heartbeat-send
    event.
  3. Server processes data through
    heartbeat_received
    filter.
  4. Client receives response via
    heartbeat-tick
    event.
<!-- Full send/receive code, interval control, and disabling examples: resources/heartbeat-templates.md -->
  1. 浏览器每隔15-120秒触发一次“tick”(默认:大多数页面为60秒,文章编辑器为15秒)。
  2. 客户端代码通过
    heartbeat-send
    事件附加数据。
  3. 服务器通过
    heartbeat_received
    过滤器处理数据。
  4. 客户端通过
    heartbeat-tick
    事件接收响应。
<!-- 完整的发送/接收代码、间隔控制和禁用示例:resources/heartbeat-templates.md -->

Hooks

钩子

HookTypeSidePurpose
heartbeat-send
EventJSAttach data before sending
heartbeat-tick
EventJSProcess server response
heartbeat-error
EventJSHandle connection errors
heartbeat_received
FilterPHPProcess data for logged-in users
heartbeat_nopriv_received
FilterPHPProcess data for logged-out users
heartbeat_settings
FilterPHPModify heartbeat interval
钩子名称类型端侧用途
heartbeat-send
事件JS发送前附加数据
heartbeat-tick
事件JS处理服务器响应
heartbeat-error
事件JS处理连接错误
heartbeat_received
过滤器PHP处理已登录用户的数据
heartbeat_nopriv_received
过滤器PHP处理未登录用户的数据
heartbeat_settings
过滤器PHP修改心跳间隔

Use Cases

使用场景

  • Post locking — warn when another user is editing the same post.
  • Autosave — periodically save draft content.
  • Session management — extend logged-in session while user is active.
  • Real-time notifications — poll for new data without WebSockets.
  • Dashboard widgets — auto-refresh stats or activity feeds.

  • 文章锁定——当其他用户正在编辑同一篇文章时发出警告。
  • 自动保存——定期保存草稿内容。
  • 会话管理——用户活跃时延长登录会话时长。
  • 实时通知——无需WebSocket即可轮询新数据。
  • 仪表盘小工具——自动刷新统计数据或活动动态。

7. wp.template (Underscore Templates)

7. wp.template(Underscore模板)

WordPress bundles
wp-util
which provides
wp.template()
for client-side HTML rendering using Underscore.js template syntax. Define templates in PHP using
<script type="text/html" id="tmpl-{name}">
blocks (typically in
admin_footer
), then render in JavaScript with
wp.template( '{name}' )
. Requires
wp-util
as a script dependency.
WordPress捆绑了
wp-util
,它提供
wp.template()
用于通过Underscore.js模板语法在客户端渲染HTML。在PHP中使用
<script type="text/html" id="tmpl-{name}">
块定义模板(通常在
admin_footer
中),然后在JavaScript中使用
wp.template( '{name}' )
进行渲染。需要将
wp-util
作为脚本依赖项。

Template Syntax

模板语法

SyntaxPurposeExample
{{ data.val }}
Escaped output (XSS-safe)
{{ data.title }}
{{{ data.val }}}
Raw HTML output (trust the source)
{{{ data.html }}}
<# code #>
JavaScript logic (if/for)
<# if (data.x) { #>
<!-- Full PHP template definition and JS rendering examples: resources/heartbeat-templates.md -->
语法用途示例
{{ data.val }}
转义输出(防XSS)
{{ data.title }}
{{{ data.val }}}
原始HTML输出(需信任数据源)
{{{ data.html }}}
<# code #>
JavaScript逻辑(if/for)
<# if (data.x) { #>
<!-- 完整的PHP模板定义和JS渲染示例:resources/heartbeat-templates.md -->

8. Common Mistakes

8. 常见错误

MistakeFix
Outputting
<script>
tags directly
Always use
wp_enqueue_script()
Loading scripts on every admin pageCheck
$hook_suffix
in
admin_enqueue_scripts
callback
Using
$
without jQuery wrapper
Wrap in
(function($) { ... })(jQuery);
— noConflict mode
Hardcoding
admin-ajax.php
URL in JS
Pass via
wp_localize_script()
using
admin_url('admin-ajax.php')
Forgetting nonce in AJAX requestsAlways create with
wp_create_nonce()
, verify with
check_ajax_referer()
Echoing after
wp_send_json_*()
These call
wp_die()
internally — no code runs after them
Not registering
nopriv
hook for public AJAX
Frontend AJAX for visitors needs
wp_ajax_nopriv_{action}
Loading jQuery from CDN instead of bundledUse the WordPress handle
jquery
— prevents version conflicts
Using
wp_localize_script()
for non-string data
Use
wp_add_inline_script()
with
wp_json_encode()
instead
Heartbeat running at 15s on non-editor pagesUse
heartbeat_settings
filter to slow it down or disable
Not declaring script dependenciesList all deps so WordPress loads them in correct order
Mixing admin-ajax and REST API unnecessarilyPick one approach per feature — REST API for new code
错误修复方案
直接输出
<script>
标签
始终使用
wp_enqueue_script()
在所有后台页面加载脚本
admin_enqueue_scripts
回调函数中检查
$hook_suffix
未包裹jQuery就使用
$
包裹在
(function($) { ... })(jQuery);
中——因为是noConflict模式
在JS中硬编码
admin-ajax.php
的URL
通过
wp_localize_script()
传递,使用
admin_url('admin-ajax.php')
AJAX请求中忘记使用nonce始终用
wp_create_nonce()
创建,用
check_ajax_referer()
验证
wp_send_json_*()
之后使用echo
这些函数内部会调用
wp_die()
——调用后不会执行后续代码
公开AJAX未注册
nopriv
钩子
面向访客的前端AJAX需要
wp_ajax_nopriv_{action}
钩子
使用CDN加载jQuery而非WordPress捆绑版本使用WordPress的
jquery
句柄——避免版本冲突
对非字符串数据使用
wp_localize_script()
使用
wp_add_inline_script()
配合
wp_json_encode()
替代
非编辑器页面的Heartbeat以15秒间隔运行使用
heartbeat_settings
过滤器减慢间隔或禁用
未声明脚本依赖列出所有依赖项,让WordPress按正确顺序加载
不必要地混合admin-ajax和REST API每个功能选择一种方案——新代码优先使用REST API