WordPress 经典编辑器自定义快捷按钮(Quicktags)完整教程 —— 含 WP 6.0 后失效修复

WordPress 经典编辑器底部那一排按钮(b、i、link、code…),其实是可以用代码自己加的——加一个"一键插入代码高亮标签"的按钮,写技术文章时能省掉大量重复劳动。

但很多人在升级到 WordPress 6.0 之后发现:以前好好的自定义按钮,一夜之间全部消失了,控制台还报 QTags is not defined。这篇文章就把 Quicktags 的用法和这个坑一次讲透。

一、Quicktags 是什么

Quicktags 是 WordPress 自带的一个轻量 JS 库(wp-includes/js/quicktags.min.js),负责经典编辑器「文本」模式那一排工具栏。它提供一个全局对象 QTags,核心方法就是 QTags.addButton()。

两个前提要清楚:

  • 只在经典编辑器的「文本 / HTML」模式出现,可视化模式下看不到;
  • Gutenberg(区块编辑器)不加载 quicktags,所以按钮在区块编辑器里永远不会出现。

二、最小可用代码

把下面这段丢进主题的 functions.php(建议用子主题,否则主题更新会覆盖):

  1. <?php
  2. add_action( 'admin_print_footer_scripts', 'my_quicktags', 11 );
  3. function my_quicktags() {
  4.     if ( ! wp_script_is( 'quicktags' ) ) {
  5.         return;
  6.     }
  7.     ?>
  8. <script>
  9. QTags.addButton( 'my_h2', 'h2', '<h2>', '</h2>', '', '二级标题', 200 );
  10. </script>
  11. <?php
  12. }

刷新文章编辑页,切到「文本」模式,工具栏最后一排就会出现一个 h2 按钮:光标选中文字点一下,自动包上 <h2></h2>。

三、addButton 的七个参数

# 参数名 必填 说明
1 id 是 按钮唯一 ID,最终 DOM id 会被加上 qt_content_ 前缀。不要与默认按钮重名
2 display 是 按钮上显示的文字
3 arg1 是 开始标签(也可传回调函数名)
4 arg2 否 结束标签。留空则该按钮是"选中包裹"型
5 access_key 否 已废弃,填 '' 即可,早年的快捷键功能现在完全不生效
6 title 否 鼠标悬停提示文字
7 priority 否 排位。1-9 第一排,11-19 第二排,21-29 第三排;不填会被挤到最后

四、WP 6.0 后按钮集体消失:原因与修复

现象

升级到 WordPress 6.0 之后,自定义按钮一个都不显示,浏览器控制台报:

Uncaught ReferenceError: QTags is not defined

根因

WP 6.0 调整了后台脚本的加载顺序,把 quicktags.min.js 的加载推后了。而 admin_print_footer_scripts 这个钩子的默认优先级是 10——你的内联脚本跑在 quicktags 之前,此时 QTags 这个全局对象还不存在,整段 JS 直接抛错中断,按钮自然一个都加不上。

这不是你代码写错了,是核心行为变了。

修复方法一:把优先级改成 11(最简单)

给 add_action 补第三个参数,值必须大于 10:

  1. <?php
  2. //                                              ↓ 关键:第三个参数 11
  3. add_action( 'admin_print_footer_scripts', 'my_quicktags', 11 );

再配合 wp_script_is( 'quicktags' ) 判断,在没有编辑器的后台页面直接跳过,避免无谓报错:

  1. <?php
  2. function my_quicktags() {
  3.     if ( ! wp_script_is( 'quicktags' ) ) {
  4.         return;   // 当前页面没有经典编辑器,不输出脚本
  5.     }
  6.     ?>
  7. <script>
  8. QTags.addButton( 'my_h2', 'h2', '<h2>', '</h2>', '', '二级标题', 200 );
  9. </script>
  10. <?php
  11. }
  12. add_action( 'admin_print_footer_scripts', 'my_quicktags', 11 );

修复方法二:wp_add_inline_script(推荐,更规范)

把脚本挂到 quicktags 这个 handle 后面,WordPress 会保证它在 quicktags 加载完之后输出,从原理上杜绝顺序问题:

  1. <?php
  2. add_action( 'admin_enqueue_scripts', function () {
  3.     wp_add_inline_script(
  4.         'quicktags',
  5.         "QTags.addButton( 'my_h2', 'h2', '<h2>', '</h2>', '', '二级标题', 200 );"
  6.     );
  7. } );

好处有三个:不写死 <script> 标签、始终保证执行顺序、当其他插件移除 quicktags 时不会跟着报错。

修复方法三:独立 JS 文件 + 声明依赖

按钮多的时候最清爽。新建 js/my-quicktags.js:

  1. QTags.addButton( 'my_h2', 'h2', '<h2>', '</h2>', '', '二级标题', 200 );
  2. QTags.addButton( 'my_h3', 'h3', '<h3>', '</h3>', '', '三级标题', 201 );

然后在 functions.php 里注册,第二个数组声明依赖:

  1. <?php
  2. add_action( 'admin_enqueue_scripts', function () {
  3.     wp_enqueue_script(
  4.         'my-quicktags',
  5.         get_template_directory_uri() . '/js/my-quicktags.js',
  6.         array( 'quicktags' ),   // ← 声明依赖,保证加载顺序
  7.         '1.0',
  8.         true
  9.     );
  10. } );

五、Gutenberg 区块编辑器下怎么办

直接说结论:Gutenberg 页面根本不加载 quicktags,上面所有代码都不会生效,wp_script_is( 'quicktags' ) 会返回 false。

三条路,选一条:

  1. 装 Classic Editor 插件——最简单,装完本文所有代码原地复活;
  2. 用「自定义 HTML」区块——直接在区块里手写标签,不要按钮;
  3. 写区块编辑器扩展——用 enqueue_block_editor_assets 挂一个真正的区块格式(Format API),这是另一套体系,工作量不小。

如果你的习惯是手写 HTML(尤其是技术站要贴代码块),方案 1 最省事。

六、实战:一套能直接用的按钮组

下面是本站正在用的配置,包含代码高亮标签按钮、标题、强调、图片,复制改改就能用:

  1. <?php
  2. /**
  3.  * 在文本编辑器工具栏追加自定义按钮
  4.  *
  5.  * 【关键】add_action 第三个参数 11 —— WP 6.0 起 quicktags.min.js 推迟加载,
  6.  *         优先级 10 时 QTags 尚未定义,会报 "QTags is not defined",按钮全部失效。
  7.  */
  8. add_action( 'admin_print_footer_scripts', 'eg_quicktags', 11 );
  9. function eg_quicktags() {
  10.     if ( ! wp_script_is( 'quicktags' ) ) {
  11.         return;
  12.     }
  13.     ?>
  14. <script type="text/javascript">
  15. // —— 代码高亮标签(配合 GeSHi 系插件)——
  16. QTags.addButton( 'eg_pre',    'pre',      '<pre>\n\n</pre>', '', '', '普通 pre', 200 );
  17. QTags.addButton( 'css_pre',   'pre-css',  '<pre lang="css" line="1" escaped="true">\n\n</pre>',        '', '', 'CSS 代码',   201 );
  18. QTags.addButton( 'phs_pre',   'pre-php',  '<pre lang="php" line="1" escaped="true">\n\n</pre>',        '', '', 'PHP 代码',   202 );
  19. QTags.addButton( 'html_pre',  'pre-html', '<pre lang="html4strict" line="1" escaped="true">\n\n</pre>', '', '', 'HTML 代码', 203 );
  20. QTags.addButton( 'js_pre',    'pre-js',   '<pre lang="javascript" line="1" escaped="true">\n\n</pre>', '', '', 'JS 代码',    204 );
  21. QTags.addButton( 'csharp_pre','pre-c#',   '<pre lang="csharp" line="1" escaped="true">\n\n</pre>',     '', '', 'C# 代码',    205 );
  22. QTags.addButton( 'lua_pre',   'pre-lua',  '<pre lang="lua" line="1" escaped="true">\n\n</pre>',        '', '', 'Lua 代码',   206 );
  23. QTags.addButton( 'epl_pre',   'pre-epl',  '<pre lang="epl" line="1" escaped="true">\n\n</pre>',        '', '', '易语言代码',  207 );
  24.  
  25. // —— 排版 ——
  26. QTags.addButton( 'p_p',    'p-zhy', '<p class="alert alert-info" role="alert"><strong>xxx </strong> ...... </p>', '', '', '提示段落', 208 );
  27. QTags.addButton( 'h_2',    'h-2',   '<h2><strong> xxx </strong></h2>', '', '', '二级标题', 209 );
  28. QTags.addButton( 'h_3',    'h-3',   '<h3><strong> xxx </strong></h3>', '', '', '三级标题', 210 );
  29. QTags.addButton( 'h_4',    'h-4',   '<h4><strong> xxx </strong></h4>', '', '', '四级标题', 211 );
  30. QTags.addButton( 'strong', 'strong','<strong> xxx </strong>', '', '', '红色强调', 212 );
  31. QTags.addButton( 'img_y',  'img',   '<p><img class="img-thumbnail" src="" alt="" loading="lazy" /></p>', '', '', '插入图片', 213 );
  32. </script>
  33. <?php
  34. }

其中 <pre lang="epl"> 那个按钮,需要 GeSHi 侧有对应的 epl.php 语言文件才会真正着色,否则只会插入标签、前台显示为纯文本。

七、进阶:带输入框的按钮

第 3 个参数除了传标签字符串,还可以传一个回调函数名,实现"弹窗输入后再插入":

  1. <?php
  2. function eg_quicktags_advanced() {
  3.     if ( ! wp_script_is( 'quicktags' ) ) {
  4.         return;
  5.     }
  6.     ?>
  7. <script>
  8. function insert_div() {
  9.     var cls = prompt( '请输入 class 名称:', '' );
  10.     if ( cls && cls !== '' ) {
  11.         QTags.insertContent( '<div class="' + cls + '">\n\n</div>' );
  12.     }
  13. }
  14. QTags.addButton( 'my_div', 'div', insert_div, '', '', '带 class 的 div', 220 );
  15. </script>
  16. <?php
  17. }
  18. add_action( 'admin_print_footer_scripts', 'eg_quicktags_advanced', 11 );

回调里用 QTags.insertContent() 把内容插到光标处。

八、避坑清单

  1. access_key 早已废弃。老教程里常见第 5 个参数填 'q'、'p' 之类,现在完全不生效;老代码里如果塞了多字符(如 'js'、'img')更是错的。留空,把提示文字挪到第 6 个参数。
  2. priority 别漏。不填的话按钮会全挤在工具栏末尾、顺序还不确定,体验很差。
  3. 只在「文本」模式可见。可视化模式下看不到是正常的,不是没生效。
  4. PHP 字符串里的 \n。想让插入的标签带换行,在单引号 PHP 字符串里写 \n 会被 JS 正确解析成换行;注意别写成 PHP 会转义的双引号形式。
  5. 内联 JS 里的引号冲突。标签属性用双引号时,JS 字符串用单引号包裹,反之亦然,避免提前闭合。
  6. 主题更新会覆盖。代码写在父主题 functions.php 的话,主题一升级全没了。用子主题,或者做成 wp-content/mu-plugins/ 下的小插件。
  7. 改完没反应先清缓存。浏览器缓存、对象缓存都可能让后台脚本停在旧版本,Ctrl+F5 强制刷新一次。

九、小结

  • Quicktags 只作用于经典编辑器的文本模式,Gutenberg 下无效;
  • WP 6.0 后按钮失效的根因是脚本加载顺序变化,修复方法是把 add_action 优先级改成 11,或改用 wp_add_inline_script;
  • 加 wp_script_is( 'quicktags' ) 判断,避免在无编辑器的后台页面报错;
  • 第 5 个参数 access_key 已废弃,第 7 个参数 priority 决定排位,别漏。

把按钮组配好之后,写技术文章时插代码块就变成一次点击的事,长期下来省的时间相当可观。


发布日期:

所属分类: Wordpress 综合 标签:



下一篇:

没有了,已经是最新文章