#ember.js
Вопрос:
У меня есть выпадающее меню со ссылками, при нажатии на которые я хотел бы, чтобы меню закрывалось.
Что-то вроде (a11y/i18n усечено):
<ul class="menu">
<li>
<LinkTo @route="myprofile">
Profile
</LinkTo>
</li>
<li>
<LinkTo @route="logout">
Logout
</LinkTo>
</li>
</ul>
Я хотел бы добавить дополнительный обработчик кликов по ссылке на, что-то вроде:
<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
бесполезным, поскольку он перезагружает страницу, как если бы переходил по ссылке, а не переходил на новый маршрут. В настоящее время мы делаем это с помощью действия hember-link, но я бы хотел найти более идиоматичный способ решения этой проблемы.
Ответ №1:
Если вам нужно выполнить дополнительную логику, вы можете реализовать перенаправление в действии вместо использования LinkTo
помощника. Для этого вам нужно ввести RouterService
в свой компонент, а затем вызвать его transitionTo
метод. Что-то вроде:
export default class ExampleComponent extends Component {
@service router;
@action
navigate(route) {
this.menuExpanded = false;
this.router.transitionTo(route);
}
}
Обратите внимание, что также существуют transitionTo()
методы из маршрута и transitionToRoute()
из контроллера, которые ведут себя как LinkTo
помощник. Но сейчас эти методы устарели, и использование RouterService
является рекомендуемым идиоматическим способом выполнения переходов в коде js.
Комментарии:
1. Это будет обрабатывать навигационную часть, но это не все, что делает linkTo. Он также создает семантически правильный
a
тег с допустимымhref
указанием на маршрут, а также добавляет некоторые классы, если текущий маршрут является активным, и в этом случае предотвращает переход. Это хорошее начало, но я надеюсь получить всеLinkTo
вместе с небольшим количеством большего.
Ответ №2:
Я написал компонент, который в основном справляется с этим, но я совершенно уверен, что в нем есть больше крайних 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>
Это становится еще более раздражающим из-за этой проблемы transitionTo
, поскольку при вызове в URL-адрес добавляются неустановленные параметры запроса, что влияет на службу общедоступного маршрутизатора. Встроенный компонент использует частный внутренний маршрутизатор, где такого поведения не существует, и, возможно, стоит использовать эту частную службу, но пока мы будем жить с передачей параметров запроса.