如何为 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 属性。如果只是跳转到登录页面,保留普通登录链接即可。
备注:内容仅供参考。
