WP DEVELOP

EP078. “搜索结果改用自定义 API,重写三栏布局”

首页 WordPress 开发课程 前端 OVERLAY 串接自定义 API · EP078
约 14 分钟· #EP078#前端 OVERLAY 串接自定义 API
🔒 登录后可标记已读

把前端搜索结果的渲染逻辑从「用 WordPress 内建 REST API、分别查 posts/pages 再手动合并」改成「用上一 Section 建好的自定义 university/v1/search 端点,一次请求拿到全部数据」。同时把结果区从简单的一栏标题列表改成三栏布局(General Information / Programs / Professors / Campuses / Events),并顺手给自定义 API 的 JSON 补上前端要用到的 postTypeauthorName 字段。这一讲先完成 General Information、Programs、Campuses 三块的输出,Professors 和 Events 的卡片/事件样式留到下一讲。


涉及文件

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

代码实现

src/modules/Search.jsgetResults() 方法重写(旧的双请求 + win/then 合并逻辑整段删除,改成单次 $.getJSON 请求自定义端点):

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

getResults() {
  $.getJSON(universityData.root_url + "/wp-json/university/v1/search?term=" + this.searchField.val(), results => {
    this.resultsDiv.html(`
      <div class="row">
        <div class="one-third">
          <h2 class="search-overlay__section-title">General Information</h2>
          ${results.generalInfo.length ? '<ul class="link-list min-list">' : "<p>No general information matches that search.</p>"}
            ${results.generalInfo.map(item => `<li><a href="${item.permalink}">${item.title}</a> ${item.postType == "post" ? `by ${item.authorName}` : ""}</li>`).join("")}
          ${results.generalInfo.length ? "</ul>" : ""}
        </div>
        <div class="one-third">
          <h2 class="search-overlay__section-title">Programs</h2>
          ${results.programs.length ? '<ul class="link-list min-list">' : `<p>No programs match that search. <a href="${universityData.root_url}/programs">View all programs</a></p>`}
            ${results.programs.map(item => `<li><a href="${item.permalink}">${item.title}</a></li>`).join("")}
          ${results.programs.length ? "</ul>" : ""}

          <h2 class="search-overlay__section-title">Professors</h2>

        </div>
        <div class="one-third">
          <h2 class="search-overlay__section-title">Campuses</h2>
          ${results.campuses.length ? '<ul class="link-list min-list">' : `<p>No campuses match that search. <a href="${universityData.root_url}/campuses">View all campuses</a></p>`}
            ${results.campuses.map(item => `<li><a href="${item.permalink}">${item.title}</a></li>`).join("")}
          ${results.campuses.length ? "</ul>" : ""}

          <h2 class="search-overlay__section-title">Events</h2>
        </div>
      </div>
    `)
    this.isSpinnerVisible = false
  })
}

关键改动点:

  • $.getJSON(url, results => {...}) 单次请求代替原本 $.when(...).then(...) 的双请求合并写法,回调用 ES6 箭头函数(避免 this 被改写)
  • 结果整体用 class="row" + 三个 class="one-third"div 做三栏布局
  • 数据来源从旧的 combinedResults 数组改成读 results.generalInfo / results.programs / results.campuses(对应自定义端点 JSON 里的分类数组)
  • 判断当前结果是否为博客文章时,字段名从内建 REST API 的 type 改成自定义 JSON 里的 postType;链接地址字段从内建的 link 改成自定义 JSON 里的 permalink
  • 无结果时的提示文案对 Programs / Campuses 额外加了「View all XXX」链接,用模板字符串拼 ${universityData.root_url}/programs,避免网站不在根目录时链接失效
  • 每次渲染完结果,在模板字符串结束后加一行 this.isSpinnerVisible = false,让用户可以立刻发起下一次搜索

[截图:前台搜索 overlay 输入关键词后,展示 General Information / Programs / Campuses 三栏布局的结果]

inc/search-route.php:给 General Info 结果补充 postTypeauthorName 属性

// wp-content/themes/fictional-university-theme/inc/search-route.php

// 新增:在 generalInfo 的关联数组里补上 postType 和 authorName
'permalink' => get_the_permalink(),
'postType' => get_post_type(),
'authorName' => get_the_author()

Hook / Function 速查

名称类型用途
$.getJSON(url, callback)jQuery 方法发一次 GET 请求并把响应 JSON 传入回调
get_post_type()WP 内建 function获取当前循环post的文章类型
get_the_author()WP 内建 function获取当前循环post的作者名

常见坑

  • 自定义 API 返回的 JSON 结构跟 WordPress 内建 REST API 不一样:标题不是嵌套在 title.rendered 里,而是直接一个 title 字段;链接字段名是自定义的 permalink 不是内建的 link——照抄旧代码字段名会导致前端显示 undefined
  • postTypeauthorName 这两个字段内建 REST API 没有,必须自己在 search-route.php 里手动加到返回的关联数组里,前端逻辑才拿得到

延伸 / 后续讲座会用到

Professors 和 Events 的自定义卡片/事件摘要样式,留到 EP079 继续完成。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 16, EP078