18

我在主页上有一个需要链接的登录框。登录框id="login在 html 中有“,我有一个这样的链接,<li><a href="#login">Login</a></li>所以单击它会将我带到该登录 div,但是当我点击刷新或直接转到带有锚点的链接时,我得到Uncaught Error: No route matched the URL 'login'

有人知道如何在 Ember 中完成这个简单的任务吗?谢谢。

更新

这是我的代码的样子:

导航

 <ul class="nav navbar-nav pull-right">
  <li><a href="#login">Signup</a></li> 
  <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
 </ul>

在页面下方的某个地方我有

<section id="login">
 -- some content
</section>
4

7 回答 7

15

查询参数

基于查询参数方法的更新答案(截至 2013 年 12 月 21 日的当前特色标志)

基于alexspellers原始 JSFiddle,完整的演示可以在这里找到:http: //jsfiddle.net/E3xPh/

在您的Router中,添加对查询参数的支持

App.Router.map ->
  @resource 'index', path: '/', queryParams: ['anchor']

使用您选择的,在方法中为查询参数Route设置一个属性。anchorsetupController

App.IndexRoute = Em.Route.extend
  setupController: (controller, context, queryParams) ->
    controller.set 'anchorLocation', queryParams.anchor

最后在你Controller做一个观察者的anchorLocation财产。

App.IndexController = Em.ArrayController.extend
  showAnchor: (->
    $elem = $(@anchorLocation)
    $scrollTo = $('body').scrollTop($elem.offset().top)
  ).observes 'anchorLocation'

现在,您可以在模板中使用以下代码滚动到锚点或将浏览器指向/#/?anchor=#login例如。

{{#linkTo anchor='#login'}}Show login{{/linkTo}}

简单的行动方法

根据您在第一个答案的评论中写的内容,可能的答案。在这里拼凑一些简单的东西。

http://jsbin.com/osEfokE/11

单击 Index 链接会将您带到 IndexRoute 并滚动到登录框,但是 URL 并未反映此更改,并且键入 #login 也不起作用。

App.ApplicationRoute = Ember.Route.extend({
    events: {
        goToLink: function(item, anchor) {
            var $elem = $(anchor);
            var $scrollTo = $('body').scrollTop($elem.offset().top);

            this.transitionToRoute(item.route).then($scrollTo);  //.transitionTo is depricated
        }
    }
});

当您想要滚动到锚点时,您将在模板中使用 goToLink,而不是使用 linkTo。

<ul>
  <li><a href="#/" {{action goToLink "index" "#login"}}>Index</a></li>
  <li>{{#linkTo about}}About{{/linkTo}}</li>
  <li>{{#linkTo contact}}Contact{{/linkTo}}</li>
</ul>
于 2013-08-29T14:51:00.747 回答
8

问题是 Ember 使用 URL 中的哈希部分来存储应用程序的当前状态。我自发地看到了两种可能的解决方案。

1 - *不要让 Ember 使用 URL 的哈希部分。* 因此使用 Ember 的HTML5 历史定位实现。这将导致 URL 像yourdomain.com/users/1/没有#.

App.Router.reopen({
  location: 'history'
});

2 - 不要使用这种技术。而是使用 jQuery滚动到相关部分。这可能看起来像这样:

<ul class="nav navbar-nav pull-right">
  <li><a {{action jumpToLogin}}>Signup</a></li> 
  <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
</ul>

并在相应的视图中:

App.YourView = Ember.View.extend({
  jumpToLogin : function(){
    $('html, body').animate({
        scrollTop: $("#login").offset().top
    }, 2000);
  }
});

对于这个小功能,这似乎有很多代码,但我想这是一个更好的用户体验,对吧?实际上,您可以通过将此逻辑提取到 mixin 中来改进这种方法,因此您不必一遍又一遍地重复它:

App.ScrollToMixin = Ember.Mixin.create({
  scrollDuration : 2000, //default
  scrollTo : function(selector){
    $('html, body').animate({
        scrollTop: $(selector).offset().top
    }, this.get("scrollDuration");
  )
});
// mix it into your View
App.YourView = Ember.View.extend(App.ScrollToMixin, {});

并在您的模板中使用它:

<ul class="nav navbar-nav pull-right">
  <li><a {{action scrollTo "login"}}>Signup</a></li> 
  <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
</ul>

PS:我没有用mixin测试过代码。我不确定字符串“登录”是否完全像那样传递给动作处理程序。所以你必须测试:-)

于 2013-08-29T08:45:51.633 回答
5

我使用了一个组件,它也可以通过操作扩展以支持查询参数。

var ScrollToComponent = Ember.Component.extend({
  tagName: 'a',
  anchor: '',

  scrollTo: function () {
    var anchor = this.get('anchor'),
      $el = Ember.$(anchor);

    if ($el) {
      Ember.$('body').scrollTop($el.offset().top);
    }
  }.on('click')
});

这是你将如何使用它:

{{#scroll-to anchor=anchor}}Jump To Anchor{{/scroll-to}}

anchor在哪里#my-id

编辑

这是一个执行此操作的 ember-cli 插件https://www.npmjs.com/package/ember-scroll-to

于 2014-11-10T16:48:10.067 回答
1

我通过kroovy 的回答中的简单操作方法在 Ember 中完成了这项工作。

由于 Ember 改变了它的 API,我不得不稍微改变一下 kroovys 的方法。

有两件事发生了变化:

  1. Ember.Route 中的事件已弃用并由 Ember.Controller 中的操作替换
  2. 而不是 transitionTo 你必须使用 transitionToRoute

这是我在 Ember 版本 1.7.0 中的工作方式

Ember 车把-模板new.hbs

{{!-- Navigation --}}
<ul>
 <li {{action 'goToLink' "new" "#part1"}}>Part 1</li>
 <li {{action 'goToLink' "new" "#part2"}}>Part 2</li>
</ul>

{{!-- content --}}
<div id="part1" class="row">...</div>
<div id="part2" class="row">...</div>

Ember App.Controller NewController.js

App.NewController = Ember.ArrayController.extend({

 actions: {

    goToLink: function(item, anchor) {
        console.log('NewController > goToLink');
        var $elem = $(anchor);
        var $scrollTo = $('body').scrollTop($elem.offset().top);

        this.transitionToRoute(item.route).then( $scrollTo);
    }
}
});
于 2014-09-14T12:40:17.840 回答
1

大多数先前答案的问题是,如果在单击其中带有“href hash/fragment/id”的“链接”时路由没有改变,那么 ember 路由器将不会触发执行大部分之前所需的钩子解决方案。

这在具有多个“标题”的页面中很明显,您希望允许用户从“导航/索引或链接列表”跳转到页面的相关部分(如服务条款或关于页面)。

在这些情况下,ember 要求您“选择完全转换”,以便即使路由没有改变但查询参数已经改变,路由器也会触发它的钩子。有关详细信息,请参阅“选择完全过渡”

注意:使用此“选择加入”时唯一记录在案的钩子是模型钩子。

我相信这种“完全过渡”选择仅用于在查询参数更改时刷新模型以进行排序或过滤等操作。

诚然,这看起来有点像 hack,但是上面的“选择加入”可以用来滚动到我们的 div /anchor 标签。将来,opt-in 可能也能够触发其他更合适的钩子(setupController 特别好)。

此外,以防其他人在谷歌搜索。我还尝试在路线上使用“willTransition”和“didTransition”操作。虽然他们在从其他路线过渡时确实被解雇了,但遗憾的是,他们在从同一条路线过渡到自己时也未能解雇。

最后,对某些人来说应该很明显(但一开始并不适合我),为了让浏览器滚动到有问题的 id,dom 需要完全加载。所以我们必须在Ember.run.schedule('afterRender',回调中执行滚动。

仅供参考,我正在使用目前普遍可用的最新 ember-cli、ember.js 和 ember-data:

  • 余烬-cli:1.13.7
  • 余烬:1.13.6
  • 余烬数据:1.13.7

应用程序/路由器.js

  this.route('about', {
    queryParams: ['anchor']
  });

路线/about.js

import Ember from 'ember';

export default Ember.Route.extend({
  queryParams: {
    anchor: {
      refreshModel: true
    }
  },
  model: function(params) {
    var aboutController = this.controllerFor('about');
    aboutController.set('anchorLocation', params.anchor);
  }
});

应用程序/控制器/about.js

import Ember from "ember";
export default Ember.Controller.extend({
  queryParams: ['anchor'],
  anchor: '',
  showAnchor: function() {
    var _this = this;
    Ember.run.schedule('afterRender', function scrollToAnchor(){
      var elem = Ember.$(_this.anchorLocation);
      elem.get(0).scrollIntoView(true);
    });
  }.observes('anchorLocation'),
});

应用程序/模板/footer.js

          <ul>
            <li>
              {{#link-to "about" (query-params anchor='#contact')}}Contact{{/link-to}}
            </li>
            <li>
              {{#link-to "about" (query-params anchor='#support')}}Support{{/link-to}}
            </li>
            <li>
              {{#link-to "about" (query-params anchor='#team')}}Team{{/link-to}}
            </li>
          </ul>
于 2015-08-20T12:22:58.570 回答
0

我的问题是,如果我从另一个页面单击目标链接,它将转到目标但不会向下滚动到页面的正确部分。几个小时后,这是我的修复:

注意:我正在使用ember-cli,emblemember 1.8

我的navigation bar(在application.emblem)中的链接

li 
 a#concept-link click=jumpToConcept
  | Le Concept 

然后,如果我已经在页面上,我只需向上滚动即可。如果我还没有在页面上,那么我会使用查询参数转到该页面concept=true

actionapplication controller

scrollToConcept: function() {
  Ember.$(document).ready(
    Ember.$('html, body').animate({
        scrollTop: Ember.$("#concept").offset().top
    }, 750)
  )
},

 //allow clicking of link with specific id to go to that part of page
jumpToConcept : function(){
  if (this.get('currentPath') === 'index') {
    this.send('scrollToConcept');
  } else {
    this.transitionToRoute('index', { queryParams: {concept: true}});
  }
}

然后index controller我添加concept query params

export default Ember.Controller.extend(

  queryParams: ['concept'],
  concept: null
}

然后,我在(我刚刚访问的页面)中添加一个scrollToConcept事件,该事件index view监听页面加载并检查concept queryParam. 如果concept=true我然后滚动到页面的概念部分。

index view

scrollToConcept: function() {
    if (this.controller.get('concept') === 'true') {
        Ember.$('html, body').animate({
        scrollTop: Ember.$("#concept").offset().top
    }, 750);
    }
}.on('didInsertElement')

然后对于 normal index links,我添加了一个设置concept=null,以便concept query param不会显示在 url 中。

链接nav bar

a click=goToIndex
  h3 id={logoClass} Happy Dining

然后在application controller我去index route,设置concept query param为null(所以它不会显示在url中)并滚动到顶部(以防它在页面上较低)

actions: {
 goToIndex: function() {
  this.transitionToRoute('index', { queryParams: {concept: null}});
  Ember.$(window).scrollTop(0);
 }
}

希望对以后的人有所帮助!!!

于 2015-02-10T13:29:23.763 回答
0

如果有人试图用 Ember 3 解决这个问题,我有一个解决方案。它使用与其他人提到的相同的 queryParams 方法,但我无法在控制器上进行任何操作。我发现唯一可行的方法是使用 route + jQuery.ready 函数。

// route/application.js
import Route from '@ember/routing/route';
import $ from 'jquery';

export default Route.extend({
  queryParams: {
    anchor: null
  },

  setupController: function(controller, context, params) {
    let anchor = params.queryParams.anchor;

    // On ready, find the anchor offset and go there
    $().ready(function() {
      let anchorOffset = $("#" + anchor).offset().top
      window.scrollTo(0, anchorOffset);
    });
  }
});

然后在模板中,像往常一样使用您的 queryParams:

{{#link-to "path.to.page" (query-params anchor="my-anchor")}}My Link{{/link-to}}

这里唯一的问题是它每次都重新加载页面,但除此之外似乎有效 - 希望它可以帮助某人。

于 2019-07-29T13:02:40.757 回答