在 Ember.js 中结合 linkTo 和 action 助手

Posted

技术标签:

【中文标题】在 Ember.js 中结合 linkTo 和 action 助手【英文标题】:Combine linkTo and action helpers in Ember.js 【发布时间】:2013-04-14 00:19:11 【问题描述】:

我需要在 Ember.js 中结合 linkTo 和操作助手。我的代码是:

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

【问题讨论】:

可能有点晚了,但是为什么你不能简单地将你的 link-to 助手包裹在像 span 这样的其他 html 元素中并在那里触发你想要的操作? Ej:&lt;span action 'yourAction'&gt; link-to 'yourRoute' link text /link-to &lt;/span&gt; 这将是 2 个 HTML 元素而不是 1 个。此外,您需要在 CSS 中进行更改。如果有可能在 1 个元素中做到这一点并且 seo 还可以,那么为什么不去做呢? ;)和1件更多的东西。如果你有几十个或几百个这样的链接怎么办。那将是您需要的 HTML 样板的两倍。 好吧,我只是不介意 2 个 html 元素呵呵 【参考方案1】:

这是在 Ember 3.11.0 之后带有 on 修饰符的样子。

<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/

【讨论】:

刚刚又遇到了这个问题......这个解决方案对我不起作用:将on 修饰符添加到LinkTo 组件原因是停止进行转换。 Ember 3.28.6. 这适用于 3.28.8,因为我刚刚将它添加到项目中。我必须确保我调用的方法有动作装饰器,但看起来效果很好。【参考方案2】:

Ember 链接操作插件

适合 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=(action 'testAction' param1 param2)
  Link to another route
/link-to

兼容性

自动化测试套件确认插件适用于 1.13 到最新的 Ember 3 版本。

它适用于 Ember 的发行版、测试版和金丝雀版。

Addon GitHub repository. 欢迎投稿。

【讨论】:

【参考方案3】:

我喜欢 Cereal Killer 的简单方法,但不幸的是它给我带来了问题。当浏览器导航到另一个路由时,它重新启动 Ember 应用程序

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

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

这实现了以下目标:

导航到路线“家” 调用了“closeNavigationMenu”操作 鼠标悬停时,浏览器会显示链接(用于 SEO 和更好的用户体验) 浏览器导航不会导致 Ember 应用重新启动

【讨论】:

【参考方案4】:

更新:请参阅下方 Michael Lang 对 Ember 1.8.1+ 的评论

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

如果您希望将链接指向的内容编入索引,最简单的方法是在其中放置一个很好的旧&lt;a href=x&gt;。最好使用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

【讨论】:

我不是 SEO 专家。但我简要听说过 Google 使用 JS 框架为网站编制索引的新方法。如果您有使用新的 JS SEO 系统的设置,他们还会查看 href 属性吗? 我认为至少在接下来的几年里,任何未来/待定的解决方案仍然会查看 href 属性。忽略锚标记将是对网络索引方式的重大改变。如果某些搜索机器人找到了运行 JS 的绝妙方法,但我看不出它不起作用,则上述解决方案可能会变得多余。 为了完善这个很好的答案,最好在调用操作之前检查链接是否被禁用(通过 this.get('_isDisabled') )。 感谢您的回答!似乎链接到帮助程序的设计自发布以来可能已更改。在 Ember 1.8.1 中,我不得不替换 this.get('controller').send(action, this.get('actionParam'));用 this.sendAction('action', this.get('actionParam'));为了让动作传播到我的路由控制器。【参考方案5】:

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

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

链接将发生,然后单击将冒泡到操作处理程序。它已记录在案(尽管是间接的)here。

编辑:更正了打开链接标签中的语法

【讨论】:

这违反了一些 a11y 准则,请不要这样做!【参考方案6】:

Ember 的链接到标签使用路由来打开新视图,因此您可以在目标路由的 setupController 方法中而不是在控制器操作中执行您想要放入链接的“动作”属性中的任何功能。

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

这仅适用于您希望每次访问路由时都执行该操作,而不是使用特定链接。

确保包含controller.set('model', model); 行以及您在其中放置的任何其他内容。

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

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

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

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

它对我很有效;希望对您有所帮助...

【讨论】:

【参考方案9】:

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

例如在控制器中你可以有这样的代码:

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

【讨论】:

为什么在 Fireup ember 教程中他们会这样做 在 Ember.js 的这个时代,您可以注入路由器服务并转换,而不必冒泡到顶部

以上是关于在 Ember.js 中结合 linkTo 和 action 助手的主要内容,如果未能解决你的问题,请参考以下文章

检查 Ember.js:获取对象(类)的类型?

检查Ember.js:获取对象的类型(Class)?

ember.js学习笔记

ember.js 和服务器

Ember.JS - 如何在同一页面中使用多个模型、控制器和视图?

ember.js里的实用方法