EP104. “Like JS 模块与点击分发逻辑”
🔒 登录后可标记已读新建 Like JS 模块,先只把「点击心形图标该走创建还是删除」这个分发逻辑写出来(用测试弹窗代替真实请求,下一讲才接 API)。判断依据就是上一讲写进 HTML 的 data-exists 属性:已经点过赞(yes)就该删除,没点过就该创建。这一讲也顺手把点击目标的定位逻辑写得比较「通用」——不管用户点在外层灰色盒子上、心形图标上还是数字上,都能正确定位到对应的 .like-box 元素,为将来可能一页多个赞按钮的场景做准备。
涉及文件
wp-content/themes/fictional-university-theme/src/modules/Like.js(新建)wp-content/themes/fictional-university-theme/src/index.js(修改)
代码实现
src/modules/Like.js(新建):
// wp-content/themes/fictional-university-theme/src/modules/Like.js
import $ from "jquery"
class Like {
constructor() {
this.events()
}
events() {
$(".like-box").on("click", this.ourClickDispatcher.bind(this))
}
ourClickDispatcher(e) {
var currentLikeBox = $(e.target).closest(".like-box")
if (currentLikeBox.data("exists") == "yes") {
this.deleteLike()
} else {
this.createLike()
}
}
createLike() {
alert("create test message")
}
deleteLike() {
alert("delete test message")
}
}
export default Like
src/index.js:导入并实例化新模块:
// wp-content/themes/fictional-university-theme/src/index.js
import Like from "./modules/Like"
// ...
const like = new Like()
关键改动点:
.on("click", this.ourClickDispatcher.bind(this))一开始就加了.bind(this)——因为ourClickDispatcher内部要调用this.createLike()/this.deleteLike(),如果不绑定,this会指向被点击的 DOM 元素而不是Like实例(这正是 Section 19 里踩过的坑,这次一开始就避免了)$(e.target).closest(".like-box")而不是直接写死$(".like-box"):用户实际点击的元素可能是外层灰色容器,也可能是里面的心形<i>图标或赞数<span>,这些内层元素本身没有data-exists属性;.closest()会从「实际被点击的元素」开始,沿着 DOM 树往上找最近的、匹配.like-box的祖先元素(包括它自身),从而保证不管点在盒子里哪个部分,都能拿到正确的目标- 这个「不管点在哪个子元素上都能正确定位」的写法,也是在为将来一个页面可能出现多个赞按钮(比如列表页每个教授卡片都有一个)做铺垫——即便这门课实际场景里一个页面永远只有一个赞按钮,作者依然按更通用、更能复用的方式来写
ourClickDispatcher(e)本身只负责「判断该创建还是删除」这一件事,具体动作各自拆到createLike()/deleteLike()方法里——沿用了 My Notes 模块里「判断逻辑」和「具体操作」分离的代码组织习惯
[截图:前台点击心形图标后浏览器弹出的 "create test message"/"delete test message" 提示框]
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
.closest(selector) | jQuery 方法 | 从当前元素自身开始(包含自身),向上查找最近的匹配选择器的祖先元素 |
常见坑
- 用
$(".like-box")写死选择器而不是基于e.target动态定位——点击事件的目标可能是内层的图标或数字元素,这些元素本身没有data-exists属性,直接判断会永远读到undefined .parents()和.closest()混淆——.parents()不包含元素自身,只从父级开始找;.closest()包含元素自身,如果自身就匹配选择器会直接返回自身。这一讲场景里点击目标一般是内层的图标/数字,不会是.like-box自身,但了解两者的差异有助于以后按需选择
延伸 / 后续讲座会用到
下一讲(part 2)开始写自定义 REST API 端点,把 createLike() / deleteLike() 里的测试弹窗换成真正的 AJAX 请求。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 20, EP104