PAYATHON 2026

如何为 WordPress 导航区块的自定义链接绑定 JavaScript 点击事件?

数据阿明

为导航链接设置自定义 CSS 类,再用 addEventListener() 绑定点击事件。属性名要使用区分大小写的 className,链接保留正常 URL,并在点击时通过 JavaScript 调用 myfunction()。

core/navigation-link 的 attrs 是区块属性,不会把所有键值直接转换成 HTML 属性。因此,添加 'onclick' => 'myfunction();' 不会自动生成点击事件。

为什么 onclick 和 javascript
(0) 没有生效?

  • onclick:核心导航链接没有提供这个区块属性,渲染逻辑也不会将它输出到链接上。
  • javascript:void(0):导航链接输出 URL 时使用 esc_url()。默认允许的协议不包含 javascript:,因此这种 URL 会被处理为空字符串,与观察到的空 href 一致。参见 esc_url() 官方文档。
  • classname:正确的区块属性名是 className。自定义类通过区块支持机制处理,通常添加到区块外层元素,而不是内部的 <a> 上。参见 customClassName 官方说明。

核心导航链接的渲染结构可以在 WordPress 导航链接源码中查看。原问题没有提供 WordPress 版本,下面的实现假设前台使用核心 Navigation 区块,且支持现有 filter。

1. 添加带 className 的导航链接

用下面的代码替换原有 filter 回调,并将其放到子主题的 functions.php 或自定义插件中:

add_filter( 'block_core_navigation_render_inner_blocks', function( $inner_blocks ) {
    $inner_blocks[] = [
        'blockName' => 'core/navigation-link',
        'attrs' => [
            'label' => 'Login',
            'url' => wp_login_url(),
            'kind' => 'custom',
            'className' => 'js-menu-login',
        ],
        'innerBlocks' => [],
        'innerHTML' => '',
        'innerContent' => [],
    ];

    return $inner_blocks;
} );

示例使用 wp_login_url() 提供正常的登录地址。即使 JavaScript 未加载,用户仍可以打开登录页面;如果需要跳转到其他页面,可以替换这个 URL。

这个 filter 接收的是 WP_Block_List,支持通过 $inner_blocks[] 追加区块,无需先转换成普通数组。参见 WordPress 官方 filter 使用说明。

2. 加载 JavaScript 并绑定点击事件

如果代码放在主题中,可以创建 assets/js/navigation-login.js,然后在 functions.php 中加载:

add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_script(
        'site-navigation-login',
        get_theme_file_uri( '/assets/js/navigation-login.js' ),
        [],
        false,
        true
    );
} );

在 navigation-login.js 中添加:

document.addEventListener('click', function (event) {
    if (!(event.target instanceof Element)) {
        return;
    }

    const link = event.target.closest(
        '.wp-block-navigation .js-menu-login > a'
    );

    if (!link) {
        return;
    }

    if (typeof window.myfunction !== 'function') {
        return;
    }

    event.preventDefault();
    window.myfunction();
});

这段代码假设已有的 myfunction() 可以通过 window.myfunction 访问。如果函数定义在 ES module 或其他局部作用域中,需要在对应作用域内绑定事件,或显式导入该函数。

closest() 可以处理点击链接内部文字或 <span> 的情况。事件委托也能处理绑定事件后才插入的匹配链接。代码只有在找到链接并确认函数存在时,才会阻止默认跳转。

如果 myfunction() 来自另一份脚本,应在 wp_enqueue_script() 的依赖数组中填写那份脚本实际注册的 handle,以确保加载顺序正确。

3. 检查类名实际添加在哪个元素上

在前台浏览器开发者工具中检查生成的 HTML。核心导航链接通常呈现为以下结构,其他自动生成的属性和类已省略:

<li class="wp-block-navigation-item js-menu-login">
    <a class="wp-block-navigation-item__content" href="…">
        <span class="wp-block-navigation-item__label">Login</span>
    </a>
</li>

因此,a.js-menu-login 通常匹配不到元素,应使用 .js-menu-login > a。如果主题或插件修改了结构,请根据实际 HTML 调整选择器。

如果仍然没有响应,依次检查前台是否存在 js-menu-login、脚本是否成功加载,以及 window.myfunction 是否确实为函数。这个 PHP filter 用于渲染导航内容,编辑器里的预览和点击行为不能直接代表前台结果。

使用时还需要注意什么?

如果没有限定目标导航,该 filter 可能会为页面上的多个 Navigation 区块都追加登录链接。只想修改其中一个导航时,需要进一步限定处理范围。

如果实际操作只是打开弹窗,使用 <button type="button"> 更符合操作控件的语义,还需要处理弹窗焦点、关闭操作和相关 ARIA 属性。如果只是跳转到登录页面,保留普通登录链接即可。

备注:内容仅供参考。