Объедините linkTo и помощников действий в Ember.js
Мне нужно объединить linkTo и помощников действий в Ember.js. Мой код:
{{#link-to 'index'}}<span {{action 'clear'}}>Clear</span>{{/link-to}}
Но я хотел бы сделать это примерно так:
{{#link-to 'index' {{action 'clear'}} }}Clear{{/link-to}}
А также:
<li>
{{#link-to 'support'}}
<span {{action 'myAction' 'support'}}>Support</span>
{{/link-to}}
</li>
Для того, чтобы:
<li>
{{#link-to 'support' {{action 'myAction' 'support'}} }}Support{{/link-to}}
</li>
Как мне этого добиться?
Решение
Проверьте мой ответ на совместимость с Ember 2.0, хорошо для решения SEO.
9 ответов
Ember Link Action addon
Недавно я разработал этот аддон, чтобы решить эту проблему с помощью стиля, совместимого с Ember 2.0 - 2.14+ (1.13 также работает!), И использовать преимущества закрывающих действий / имен действий. Это нормально для SEO!
Установить аддон
ember install ember-link-action
использование
Вы можете передать закрывающее действие как invokeAction
парам к {{link-to}}
составная часть:
{{#link-to 'other-route' invokeAction=(action 'testAction')}}
Link to another route
{{/link-to}}
Вы также можете использовать имя действия вместо действия закрытия:
{{#link-to 'other-route' invokeAction='testAction'}}
Link to another route
{{/link-to}}
Для передачи параметров в действие вы можете использовать:
{{#link-to 'other-route' invokeAction=(action 'testAction' param1 param2)}}
Link to another route
{{/link-to}}
Совместимость
Автоматизированный набор тестов подтверждает, что аддон работает с 1.13 до последних выпусков Ember 3.
Работает с выпуском, бета и канареек Ember.
Аддон GitHub хранилище. Вклад приветствуется.
Обновление: см. Комментарий Майкла Ланга ниже для Ember 1.8.1+
Проблема с ответом Мыслика (не используется link-to
на всех, но вместо этого с помощью action
а потом transitionToRoute
) это то, что это бесполезно для SEO, боты поисковых систем ничего не увидят.
Если вы хотите, чтобы то, на что указывает ваша ссылка, было проиндексировано, проще всего иметь старый добрый <a href=x>
там. Лучше всего использовать link-to
так что ваши URL ссылки синхронизируются с вашими URL маршрута. Решение, которое я использую, дает как действие для выполнения работы, так и удобное link-to
индексировать страницы.
Я переопределяю некоторые функции Ember.LinkView
:
Ember.LinkView.reopen({
action: null,
_invoke: function(event){
var action = this.get('action');
if(action) {
// There was an action specified (in handlebars) so take custom action
event.preventDefault(); // prevent the browser from following the link as normal
if (this.bubbles === false) { event.stopPropagation(); }
// trigger the action on the controller
this.get('controller').send(action, this.get('actionParam'));
return false;
}
// no action to take, handle the link-to normally
return this._super(event);
}
});
Затем я могу указать, какое действие предпринять и что передать в Handlebars:
<span {{action 'view' this}}>
{{#link-to 'post' action='view' actionParam=this}}
Post Title: {{title}}
{{/link-to}}
</span>
В контроллере:
App.PostsIndexController = Ember.ArrayController.extend({
actions: {
view: function(post){
this.transitionToRoute('post', post);
}
}
}
Таким образом, когда я кеширую отрендеренную копию страницы и передаю ее индексирующему боту, он увидит реальную ссылку с URL и проследит за ней.
(обратите внимание также, что transitionTo
в настоящее время устарела в пользу transitionToRoute
)
Ни одна из этих комбинаций не будет работать в Ember.js, но вам не нужно объединять эти два помощника. Почему бы вам просто не использовать хелпер действий и позволить ему переходить к контроллеру или маршруту? Там вы можете использовать transitionToRoute
в контроллере или transitionTo
в пути.
Например, в контроллере вы можете иметь такой код:
App.PostsController = Ember.ArrayController.extend({
clear: function () {
// implement your action here
this.transitionToRoute('index');
}
});
Это прекрасно работает в 1.6.0-бета.5:
<span {{action "someAction"}}>
{{#link-to "some.route"}}
Click Me
{{/link-to}}
</span>
Ссылка произойдет, и затем щелчок всплывет до обработчика действия. Это задокументировано (хотя и косвенно) здесь.
Изменить: исправлен синтаксис при открытии тега ссылки
Мне нравится подход Cereal Killer за его простоту, но, к сожалению, для меня это проблема. Когда браузер переходит на другой маршрут, он перезапускает приложение Ember.
Начиная с Ember 2.6, используется следующий простой подход:
<span {{action 'closeNavigationMenu'}}>
{{#link-to 'home' preventDefault=false}}
Go Home
{{/link-to}}
</span>
Это обеспечивает следующее:
- перемещается по маршруту "домой"
- вызывается действие 'closeNavigationMenu'
- при наведении курсора в браузере отображается ссылка, по которой будет следовать (для SEO и лучшего UX)
- навигация в браузере не приводит к перезагрузке приложения Ember
Имея ту же проблему, я нашел это простое решение:
{{#linkTo eng.rent class="external-button"}}<div class="internal-button" {{action "updateLangPath"}} >X</div>{{/linkTo}}
затем, управляя внешней кнопкой и внутренней кнопкой классов CSS в таблице стилей, я убедился, что "внутренняя кнопка" покрывает всю область "внешней кнопки"; таким образом невозможно нажать на внешнюю кнопку, не нажимая на внутреннюю кнопку.
Это хорошо работает для меня; надеюсь, что это может помочь...
Вот как я решил эту проблему в нашем демонстрационном приложении для книги O'Reilly Ember.js: https://github.com/emberjsbook.
Вы можете увидеть полный источник здесь: https://github.com/emberjsbook/rocknrollcall
По мнению:
{{#if artistsIsChecked}}
{{#if artists.length}}
<h3>Artists</h3>
<ul class="search-results artists">
{{#each artists}}
<li><a {{action 'viewedArtist' this.enid }}>{{name}}</a></li>
{{/each}}
</ul>
{{/if}}
{{/if}}
И контроллер:
App.SearchResultsController = Em.ObjectController.extend({
actions: {
viewedArtist: function(enid) {
this.transitionToRoute('artist', enid);
},
viewedSong: function(sid) {
this.transitionToRoute('song', sid);
}
},
needs: ['artists', 'songs'],
artistsIsChecked: true,
songsIsChecked: true,
artists: [],
songs: []
});
Вот как это будет выглядеть после Ember 3.11.0 с
on
модификатор.
<LinkTo
{{on "click" this.recordMetrics}}
@route="post.see-all"
@model={{@model}}
@bubbles={{false}}>
Link Me
</LinkTo>
bubbles
показан только для иллюстрации LinkTo API.
Теги ссылки на Ember используют маршруты для открытия новых представлений, поэтому вы можете выполнять любые функции, которые хотите добавить в атрибут действия action ссылки в setupController
метод целевого маршрута вместо действия контроллера.
Смотрите здесь в руководстве Ember: http://emberjs.com/guides/routing/setting-up-a-controller/
Это работает только в том случае, если вы хотите выполнять действие при каждом доступе к маршруту, в отличие от конкретных ссылок.
Не забудьте включить controller.set('model', model);
линия вместе с тем, что вы положили туда.