EP097. “新笔记真实数据渲染与事件委托修复”
🔒 登录后可标记已读接上一讲,做两件收尾工作:① 把新建笔记时的占位文字 imagine real data here 换成用 REST API 响应里的真实数据(ID、标题、正文)拼出跟其他笔记完全一致的 HTML 结构;② 修复「新建出来的笔记,编辑/删除按钮点了没反应」的问题——原因是这些按钮是页面加载完之后才动态插入的,而最初的事件绑定方式只对页面加载时就存在的元素生效,需要改成事件委托(event delegation)写法。
涉及文件
wp-content/themes/fictional-university-theme/src/modules/MyNotes.js(修改)
代码实现
events():把三个针对列表内按钮的绑定,从「直接绑定」改成「委托给外层容器」:
// wp-content/themes/fictional-university-theme/src/modules/MyNotes.js
events() {
$("#my-notes").on("click", ".delete-note", this.deleteNote)
$("#my-notes").on("click", ".edit-note", this.editNote.bind(this))
$("#my-notes").on("click", ".update-note", this.updateNote.bind(this))
$(".submit-note").on("click", this.createNote.bind(this)) // 新建表单是固定不变的,不需要委托
}
createNote():success 回调里用模板字符串拼出跟真实笔记一致的 HTML:
// wp-content/themes/fictional-university-theme/src/modules/MyNotes.js
success: response => {
$(".new-note-title, .new-note-body").val("")
$(`
<li data-id="${response.id}">
<input readonly class="note-title-field" value="${response.title.raw}">
<span class="edit-note"><i class="fa fa-pencil" aria-hidden="true"></i> Edit</span>
<span class="delete-note"><i class="fa fa-trash-o" aria-hidden="true"></i> Delete</span>
<textarea readonly class="note-body-field">${response.content.raw}</textarea>
<span class="update-note btn btn--blue btn--small"><i class="fa fa-arrow-right" aria-hidden="true"></i> Save</span>
</li>
`)
.hide()
.prependTo("#my-notes")
.slideDown()
console.log("Congrats")
console.log(response)
}
关键改动点:
- 事件委托写法:
$("#my-notes").on("click", ".delete-note", callback)跟直接绑定$(".delete-note").on("click", callback)的区别是——监听器实际挂在外层容器#my-notes(这个元素页面加载时就存在,不会变),第二个参数.delete-note是一个「筛选条件」,意思是「只要点击事件冒泡到#my-notes时,实际点击的元素匹配这个选择器,才执行回调」。这样不管.delete-note元素是页面加载时就有的,还是之后动态插入的,都能被正确响应,因为判断是点击发生的那一刻才做的,不是绑定的那一刻 .submit-note(新建表单的提交按钮)不需要用委托写法,因为这个按钮从页面加载起就一直存在、不会被动态创建,直接绑定即可- 新建成功后的 HTML 结构直接复制自
page-my-notes.php里已有的笔记条目模板,字段来源全部换成response(WordPress REST API 创建成功后,会把新文章的完整数据回传回来):response.id对应data-id,response.title.raw/response.content.raw对应标题和正文——.raw是因为 REST API 的标题/正文字段底下有raw(原始未渲染内容)和rendered(渲染后的 HTML)两个子属性,这里要的是原始文字,不是渲染过的 HTML - 新插入的
<li>结构跟page-my-notes.php里 PHP 生成的完全一致(readonly属性、note-title-field/note-body-field等 class 名都对齐),这样它才能被前面改造过的事件委托正确识别、之后的编辑/删除/保存操作才能对它生效
[截图:前台新建笔记后,用服务器真实数据渲染出的新笔记条目,样式跟其他已有笔记完全一致]
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
.on(event, selector, handler) | jQuery 方法(事件委托写法) | 把事件监听器挂在稳定存在的祖先元素上,用选择器筛选实际触发的子元素,对动态插入的元素依然有效 |
REST API 响应里的 .raw / .rendered | WP REST API 响应字段结构 | raw 是数据库原始内容,rendered 是转换成最终 HTML 后的内容,按需选用 |
常见坑
- 用
$(".edit-note").on("click", ...)这种直接绑定方式处理「可能动态新增」的元素——只对绑定那一刻已存在于页面上的元素生效,之后新插入的同类元素不会有反应,必须改成挂在稳定外层容器上的事件委托写法 - 混淆
response.title.raw和response.title.rendered——两者都能读到标题文字,但语义不同,rendered已经过 WordPress 处理(可能包含转义后的 HTML 实体),这里要的是干净的原始文字,用raw
延伸 / 后续讲座会用到
到这里 CRUD 四个操作在前端全部跑通,但目前只有 Administrator/Editor 账号能创建笔记(因为 note 文章类型的默认权限还是继承自更高权限角色)。下一讲要给 Subscriber 角色开放创建/编辑/删除私人笔记的权限,同时要注意别因此破坏网站的安全性。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 19, EP097