在Ember.js中组合linkTo和动作助手

时间:2013-04-20 19:37:32

标签: javascript ember.js handlebars.js htmlbars ember-components

我需要在Ember.js中组合linkTo和action helpers。我的代码是:

{{#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>

我怎样才能做到这一点?

解决方案

Check my answer for Ember 2.0 compatible, OK for SEO solution.

9 个答案:

答案 0 :(得分:28)

Ember Link Action插件

我最近开发了这个插件来解决这个问题,用 Ember 2.0 - 2.14+兼容 1.13也可以!)风格并利用关闭操作/动作名称。 这对SEO来说没问题!

安装插件

ember install ember-link-action

用法

您可以将invokeAction param的关闭操作传递给{{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的发行版,测试版和金丝雀版。

Addon GitHub repository.欢迎提供捐助。

答案 1 :(得分:18)

更新:请参阅下面的Michael Lang对Ember 1.8.1 +

的评论

Myslik的答案(完全没有使用link-to而是使用action然后使用transitionToRoute)的问题在于它对SEO无用,搜索引擎机器人什么也看不见。

如果您希望链接所指向的内容被编入索引,那么最简单的就是拥有一个好的旧<a href=x>。最好使用link-to,以便您的链接网址与路线网址保持同步。我使用的解决方案既提供了执行工作的操作,也提供了方便的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

答案 2 :(得分:17)

这些组合都不适用于Ember.js,但您不需要将这两个帮助器组合在一起。为什么不直接使用动作助手并让它冒泡到控制器或路线?在那里,您可以在控制器中使用transitionToRoute或在路由中使用transitionTo

例如在控制器中,您可以使用以下代码:

App.PostsController = Ember.ArrayController.extend({
    clear: function () {
        // implement your action here
        this.transitionToRoute('index');
    }
});

答案 3 :(得分:10)

这在1.6.0-beta.5中运行良好:

<span {{action "someAction"}}>
  {{#link-to "some.route"}}
    Click Me
  {{/link-to}}
</span>

链接将发生,然后点击将冒泡到动作处理程序。它被记录(虽然是间接的)here

编辑:更正了打开链接标记

的语法

答案 4 :(得分:7)

我喜欢Cereal Killer的简洁方法,但遗憾的是它对我来说是一个问题。当浏览器导航到另一个路由时,重新启动Ember应用程序

从Ember 2.6开始,以下简单方法就可以解决问题:

<span {{action 'closeNavigationMenu'}}> {{#link-to 'home' preventDefault=false}} Go Home {{/link-to}} </span>

这实现了以下目标:

  • 导航到路线&#39; home&#39;
  • 行动&#39; closeNavigationMenu&#39;被调用
  • 在鼠标悬停时,浏览器显示将遵循的链接(对于SEO和更好的用户体验)
  • 浏览器导航不会导致重新启动Ember应用

答案 5 :(得分:3)

遇到同样的问题,我找到了这个简单的解决方案:

{{#linkTo eng.rent class="external-button"}}<div class="internal-button" {{action "updateLangPath"}} >X</div>{{/linkTo}}

然后,在样式表中管理css类外部按钮和内部按钮,我确保“内部按钮”覆盖整个“外部按钮”区域;这样就无法在不点击内部按钮的情况下点击外部按钮。

对我来说效果很好;希望它可以帮助...

答案 6 :(得分:3)

这就是我在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: []
});

答案 7 :(得分:0)

Ember的链接标记使用路径打开新视图,因此您可以在目标路径的setupController方法中执行链接的“action”属性中的任何功能,而不是在控制器操作中执行

请参阅Ember指南: http://emberjs.com/guides/routing/setting-up-a-controller/

这仅适用于每次访问路径时都要执行操作的情况,而不是特定链接。

确保包含controller.set('model', model);行以及其他任何内容。

答案 8 :(得分:0)

这是使用 on 修饰符的 Ember 3.11.0 之后的样子。

<LinkTo
  {{on "click" this.recordMetrics}}
  @route="post.see-all"
  @model={{@model}}
  @bubbles={{false}}>
  Link Me
</LinkTo>

bubbles 仅用于说明 LinkTo API。

https://blog.emberjs.com/ember-3-11-released/