如何使用Stimulus和localStorage保存最近浏览的页面列表

创建”最近浏览的页面”列表可以通过提供简单的导航和最近访问内容的历史记录来显著增强用户体验。既然我们已经在使用Rails,我们将利用Stimulus。此外,我们将使用localStorage而不是在服务器上存储信息,以便在会话之间持久化浏览的页面数据。

为什么使用Stimulus和localStorage

通常对于UI交互,我更喜欢保持尽可能轻量。这就是为什么我更喜欢AlpineJS而不是Stimulus。

然而,在这种情况下,Stimulus是一个不错的选择,因为JavaScript中有更多的逻辑。

我们还将使用localStorage作为客户端存储机制。它非常适合保存页面历史等非敏感信息,因为即使用户刷新或关闭浏览器后数据仍然存储。

使用localStorage的缺点是,如果用户从另一台计算机登录,这不会同步。可以通过在Stimulus控制器中添加额外的逻辑来同步这些信息,但如果你的用例像我的一样,这可能不是必需的。

目标

我们的目标是构建一个最近浏览的页面列表,它可以:

  • 跟踪用户访问的页面。
  • 存储元数据,如页面名称和简短描述。
  • 显示最多20个最近访问的页面。
  • 使用localStorage在会话之间持久化这些数据。

Stimulus控制器

下面是一个处理用户访问页面的跟踪和存储的Stimulus控制器:

// app/javascript/controllers/recently_viewed_controller.js
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["currentPath"];

  connect() {
    if (this.currentPathTargets.length !== 0) {
      let name = this.currentPathTarget.dataset.name;
      this.saveCurrentPath(name);
    }
  }

  saveCurrentPath(name) {
    let path = window.location.pathname;

    // 创建包含path、name和description的对象
    let pathObject = { path: path, name: name };

    // 删除具有相同path的现有对象
    let visitedPaths = this.removePathsContaining(path);

    // 将新对象添加到数组开头
    visitedPaths.unshift(pathObject);

    // 只保留最近的20条记录
    if (visitedPaths.length > 20) {
      visitedPaths = visitedPaths.slice(0, 20);
    }

    // 将更新后的数组保存回localStorage
    localStorage.setItem("visitedPath", JSON.stringify(visitedPaths));
  }

  removePathsContaining(substring) {
    // 从localStorage获取现有数组
    let visitedPaths = JSON.parse(localStorage.getItem("visitedPath")) || [];

    // 过滤掉path包含substring的对象
    visitedPaths = visitedPaths.filter(
      (item) => !item.path.includes(substring)
    );

    return visitedPaths;
  }

  resetPaths() {
    // 从localStorage清除visitedPath项
    localStorage.removeItem("visitedPath");
  }
}

要激活此控制器并跟踪特定页面,你需要将此添加到body标签:

<body data-controller="smooth-scroll recently-viewed">
  <div data-recently-viewed-target="currentPath" data-page-name="<%= @page_name %>">
  </div>
  /* 你的代码 */
</body>

你可以选择重构上面的代码或将它们组合。在我的用例中,我想将控制器添加到body标签以激活它,然后如果我添加了内部div标签,则可选地保存页面。

从localStorage使用列表

现在你有了列表,可以用类似这样的方式访问它:

window.recentlyVisitedPaths = JSON.parse(localStorage.getItem("visitedPath")) || [];

值现在将作为JSON返回,你可以使用Stimulus或类似的东西来渲染它。

最后更新于 2024年8月31日