在 Octane 中向 LinkTo 添加额外的操作

Add Extra Actions to LinkTo in Octane

我有一个带有 link 的下拉菜单,单击 link 时我希望关闭菜单。

类似于(a11y/i18n 截断):

<ul class="menu">
    <li>
        <LinkTo @route="myprofile">
            Profile
        </LinkTo>
    </li>
    <li>
        <LinkTo @route="logout">
            Logout
        </LinkTo>
    </li>
</ul>

我想向 link 添加一个额外的点击处理程序,例如:

<ul class="menu">
    <li>
        <LinkTo @route="myprofile" {{on "click" this.closeMenu}}>
            Profile
        </LinkTo>
    </li>
    <li>
        <LinkTo @route="logout" {{on "click" this.closeMenu}}>
            Logout
        </LinkTo>
    </li>
</ul>

然而,这使得 LinkTo 变得毫无用处,因为它会重新加载页面,就像跟随 link 而不是转换到新路线一样。我们目前正在使用 hember-link-action 执行此操作,但我很想找到一种更惯用的方法来解决此问题。

如果您需要执行额外的逻辑,您可以在操作中实现重定向,而不是使用 LinkTo 助手。为此,您需要将 RouterService 注入到您的组件中,然后调用它的 transitionTo 方法。类似于:

export default class ExampleComponent extends Component {
  @service router;

  @action
  navigate(route) {
    this.menuExpanded = false;
    this.router.transitionTo(route);
  }
}

请注意,还有来自 Route 的 transitionTo() 方法和来自 Controller 的 transitionToRoute() 方法,它们的行为类似于 LinkTo 助手。但是现在不推荐使用这些方法,使用 RouterService 是在 js 代码中进行转换的 recommended 惯用方式。

我已经编写了一个组件来主要处理这个问题,但我很确定 LinkTo 中有更多的边缘情况然后我已经涵盖(例如它不涵盖通过的模型或型号列表)。我将其命名为 <LinkToWithAction />,它看起来像:

<a href={{this.href}} class={{if this.isActive "active"}} {{on "click" this.navigate}} >
    {{yield}}
</a>
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class LinkToWithActionComponent extends Component {
  @service router;

  get href() {
    return this.router.urlFor(this.args.route, {
      queryParams: this.queryParams,
    });
  }

  get isActive() {
    return this.router.isActive(this.args.route);
  }

  get queryParams() {
    return this.args.queryParams ?? {};
  }

  @action
  navigate(evt) {
    evt.preventDefault();
    this.args.action();
    this.router.transitionTo(this.args.route, {
      queryParams: this.queryParams,
    });
  }
}

它被称为:

<LinkToWithAction
  @route="mymaterials"
  @action={{set this.isOpen false}}
  @queryParams={{hash course=null}}
>
  {{t "general.myprofile"}}
</LinkToWithAction>

这个 issuetransitionTo 会在调用 URL 时将未设置的 queryParams 添加到 URL,这会影响 public 路由器服务,这让这变得更加烦人。内置组件使用不存在这种行为的私有内部路由器,使用该私有服务可能值得,但现在我们将接受传递查询参数。