WP DEVELOP

EP063. “键盘快捷键与禁止背景滚动”

首页 WordPress 开发课程 LIVE SEARCH AJAX · EP063
约 11 分钟· #EP063#LIVE SEARCH AJAX
🔒 登录后可标记已读

📌 并入 EP062(Preventing the Text Field Suggestions Pop-up): 作者提醒,浏览器自带的「输入历史自动补全建议」弹窗跟自定义的搜索 overlay 放一起看起来很别扭,如果不想要这个原生建议弹窗,可以给搜索的 <input> 元素加上 autocomplete="off" 这个属性。这是一句话的小技巧,没有配套操作步骤,也没有 -end 代码快照能对照(对照过 47/48/49 三个 -end 代码夹的 footer.php,都没有实际加上这个属性),本笔记只记录这个知识点,实际要不要加、加不加得上以你自己项目为准。

继续给 Search.js 加两个体验细节:① overlay 打开时锁住背景页面不让滚动,关闭时恢复;② 加键盘快捷键——按 S 键打开 overlay,按 Esc 键关闭。做键盘快捷键的过程中顺带讲了 keyup vs keydown 的区别,以及为什么要在 constructor 里额外记录一个「overlay 是否已打开」的状态,而不是每次都去读 DOM 判断

涉及文件

  • wp-content/themes/fictional-university-theme/src/modules/Search.js (修改)

代码实现

// wp-content/themes/fictional-university-theme/src/modules/Search.js

class Search {
  constructor() {
    this.openButton = $(".js-search-trigger")
    this.closeButton = $(".search-overlay__close")
    this.searchOverlay = $(".search-overlay")
    this.isOverlayOpen = false          // 新增:记录 overlay 当前开关状态
    this.events()
  }

  events() {
    this.openButton.on("click", this.openOverlay.bind(this))
    this.closeButton.on("click", this.closeOverlay.bind(this))
    $(document).on("keydown", this.keyPressDispatcher.bind(this))   // 新增:全局监听键盘事件
  }

  // 新增:根据按下的键码决定要不要开关 overlay
  keyPressDispatcher(e) {
    if (e.keyCode == 83 && !this.isOverlayOpen) {
      this.openOverlay()
    }

    if (e.keyCode == 27 && this.isOverlayOpen) {
      this.closeOverlay()
    }
  }

  openOverlay() {
    this.searchOverlay.addClass("search-overlay--active")
    $("body").addClass("body-no-scroll")   // 新增:打开时禁止背景页面滚动
    console.log("our open method just ran")  // 新增:调试用,确认方法确实执行
    this.isOverlayOpen = true              // 新增
  }

  closeOverlay() {
    this.searchOverlay.removeClass("search-overlay--active")
    $("body").removeClass("body-no-scroll")  // 新增:关闭时恢复滚动
    console.log("our close method just ran")  // 新增:调试用,确认方法确实执行
    this.isOverlayOpen = false               // 新增
  }
}

export default Search

要点:

  • body-no-scroll 这个 CSS class(overflow: hidden)在更早的讲座里就已经写进 search-overlay.scss 了,这一讲只是在 JS 里对 <body> 加/减这个 class。
  • 键盘监听绑在 $(document) 上而不是某个具体元素,因为「按键」这个事件不需要限定在某个元素被点击/聚焦的前提下,整个页面任何地方按键都要能响应
  • 每个键盘按键都有一个数字 keyCodeS 是 83,Esc 是 27。判断方式是在事件回调的参数(e)里读 e.keyCode,可以用 console.log(e.keyCode) 自己试出任意按键的编码。
  • keyup(松开键才触发一次)和 keydown(按住不放会连续触发多次)是有区别的:作者一开始想用 keyup,后来测试发现按住不放会有点「延迟感」,改成 keydown 立即响应,但 keydown 按住不放会不断重复触发方法。为了避免按住一个键就疯狂重复调用 openOverlay/closeOverlay才在 constructor 里加了 this.isOverlayOpen 这个状态属性:只有「当前是关的」才允许打开,只有「当前是开的」才允许关闭,重复触发时条件不满足就什么都不做。
  • 作者特别强调:判断 overlay 是否已打开,宁可用一个普通 JS 属性(this.isOverlayOpen)来记录状态,也不要用 jQuery 去读 DOM 上有没有 search-overlay--active 这个 class 来判断——读写 DOM 比读写 JS 变量慢得多,应该尽量避免。

Hook / Function 速查

名称类型用途
$(document).on("keydown", handler)jQuery监听整个页面范围内的键盘按下事件
e.keyCode事件对象属性读取本次按键对应的数字编码,用来判断按的是哪个键
keydown vs keyup键盘事件类型keydown 按下瞬间触发且会随长按重复触发;keyup 只在松开时触发一次
this.isOverlayOpen自定义属性(状态标记)记录 overlay 当前开关状态,避免重复触发同一方法,也避免频繁读 DOM

常见坑

  • 一开始把 "keyUp" 写成大写 U(keyUp)导致事件完全不触发,jQuery 的事件名要全小写 keyup/keydown
  • keydown 时如果不加「当前状态」判断,长按一个键会让 openOverlay/closeOverlay 被反复调用多次(虽然在这个场景下不会直接卡死浏览器,但是坏习惯,容易在更复杂功能里出问题)。
  • autocomplete="off"(EP062 提到的技巧)目前代码快照里没有实际加上,只是作者口头提醒,视需要自行加到搜索 <input> 上。

延伸 / 后续讲座会用到

this.isOverlayOpen 这个状态属性后面会继续在 EP065 里被用来判断「按 S 键时如果有其他输入框正在被聚焦就不要打开 overlay」的逻辑。计时器相关的功能(管理输入时的等待时间)会在下一讲 EP064 开始写。

Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 13, EP062, EP063