Backbone: 除非更改哈希值,否则 router.navigate 不会调用路由器

创建于 2011-10-02  ·  22评论  ·  资料来源: jashkenas/backbone

我正在尝试使用没有 hashbangs 的 URL,这导致了一些悲伤。

当我测试时,我这样做了。

<a href="#" onclick="router.navigate('/albums/<%= album.id %>', true); return false;">Show</a>

URL 已更新,但未调用我的路由器。 起初我以为路线不匹配,但如果我刷新页面,路线就成功匹配了。

然后我尝试了这个:

<a href="#" onclick="router.navigate('/albums/<%= album.id %>', true);">Show</a>

一切正常,似乎只有在触发 hashchange 时才会调用路由器。

最有用的评论

这确实是router.navigate()一个有趣行为,我之前在尝试强制重新加载路由时遇到过这种行为。 这是我最终做的:

Backbone.history.loadUrl( Backbone.history.fragment )

这不是 _explictly_ 记录为 API 的一部分,但它肯定可以完成工作。 对我来说router.navigate( 'current/path', true )应该触发路由处理程序再次被调用似乎是合理的。

还有人关心这个吗?

所有22条评论

如果我删除初始 /
猜猜它必须与您的路线完全匹配

这确实是router.navigate()一个有趣行为,我之前在尝试强制重新加载路由时遇到过这种行为。 这是我最终做的:

Backbone.history.loadUrl( Backbone.history.fragment )

这不是 _explictly_ 记录为 API 的一部分,但它肯定可以完成工作。 对我来说router.navigate( 'current/path', true )应该触发路由处理程序再次被调用似乎是合理的。

还有人关心这个吗?

我也遇到了这个问题。 这是我的具体用例:

我正在使用媒体查询为所有屏幕尺寸提供响应式界面。 我的视图中有一些元素不响应媒体查询,所以我编写了一个函数来监听调整大小事件并在需要时重新渲染页面。 而不是参考和呈现个人观点,我想我只会打电话

router.navigate(Backbone.history.fragment, true)

我宁愿根本不必参考 Backbone.history。 如果路由器有刷新或重新加载方法,那就最好了:

router.refresh(true);

我遇到过同样的问题。 @Ansman你能展示一下你的路线吗? 我的问题是在获取散列时,历史记录会自动删除前导斜杠,因为它是默认根。

是的——你永远不应该有一个前导斜杠......无论是在你的路线中还是在你的导航()调用中。 也就是说,在 master 上有一个强制删除所有前导斜杠的提交,所以这应该不再导致错误行为。

最后,是的,您的路由器应该只在路由实际更改时才触发。

我想指出,即使在散列中没有更改路由,对 router.navigate("route", true) 的显式调用也应该触发路由

@danroberts如果哈希没有改变,目前似乎不可能强制触发路由。 我试过 router.navigate("route/", {trigger:true}); 它不起作用。 一个快速的技巧是简单地调用router.route_name()

@olalonde我一直在使用@wookiehangover上面的方法,效果很好。 我刚刚编写了一个自定义函数,用于检查我尝试去的路由是否与当前哈希相同,然后调用 router.navigate 或 history.loadURL。

这可能是选项数组的一部分似乎是合理的,如果您希望它无论如何都触发路由,则类似于refresh:true 。 此外,也许文档的更新似乎是有序的,因为 {trigger: true} 在逻辑上会触发路由......

这是我关闭此错误时遇到的问题:

使用backbone的一个关键点是处理路由的解析,然后根据路由调用一个函数。 缺乏直接通过主干确定“重新加载”是否可以的能力,我们必须为此做一些事情:

        if (url == window.location.pathname + window.location.search) {
            Backbone.history.loadUrl(url);
            return false;
        }
        else if (app.router.isHandled(url)) {
            Backbone.history.navigate(url, {
                trigger: true
            });
            return false;
        }

这行得通吗? 是的,但确实感觉这是一个完全有效的用例,在平台中会很好。

仅供参考,我在此线程之前看到了 #1214 并发布了相同的评论。

Backbone Router 不允许这种类型的操作,因为它会监听 url 更改事件以触发任何路由操作。

您需要拦截触发动作的控件并重置路由器的动作。

我在这里创建了一个 jsFiddle 示例:
http://goo.gl/wPulo

和一篇博客文章:
http://goo.gl/mJM2i

今天遇到这个问题,只想加上我的 2 美分:

似乎不直观的行为,当显式设置trigger: true ,除非散列已更改,否则它不会触发事件。

无论条件如何,我的投票都支持trigger: true触发路线。

一个现实世界的例子是,当您想要刷新当前所在的页面时,这与trigger: true的当前行为是不可能的。

+1 用于 KenPerkins 方法或类似集成到 BB 路由器的方法。

如果 { trigger: true } 被传递,则在同一页面上为流程导航 +1

我花了 3 个小时试图找出roter.navigate()方法在我的应用程序上不起作用的原因。 我认为,BB 文档应该包含有关此问题的通知。

我丑陋但快速的解决方案是在实际调用之前调用router.navigate()方法。

router.navigate();
router.navigate("app", true);

目前,它奏效了。 但是如果有refresh:true选项,我肯定会使用它......

只是留下我的想法,因为这是我今天刚刚遇到的一个问题。 当您将{trigger: true}选项哈希显式传递给 router.navigate 时,不会调用该路由,这似乎非常不直观。 我很乐意看到添加refresh:true选项,例如@onuradsay建议的选项。

+1 @patrickod@onuradsay的想法的实用性

+1。 我们应该仍然能够接收事件,然后在我们的应用程序中确定是否需要刷新。 我们可以通过上面提到的许多技巧来解决这个问题,但它不是很干净。 我认为这种行为很常见,可以将其放入路由器中。

恐怕这不会发生。 人们要求它实际上比无条件地触发事件更能推动_remove_ trigger:true 。 让我解释:

Backbone 中的事件都是在状态改变时收到通知。 就像在模型中一样,做:

model.set({title: "Boom"})
model.set({title: "Boom"})

...不会第二次触发事件,因为状态没有改变...尝试导航到您已经所在的位置_不是_状态更改,并且不会触发事件。

如果您想在单击按钮时触发回调 - 只需添加回调。 或者,如果您想使用 Backbone 的事件来执行此操作——只需调用 object.trigger("myEvent")

似乎不是trigger:true它应该假设为 true 并且有silent:false选项。

如果我们不添加这个功能,我们将总是不得不在我们的按钮处理程序中做这样的事情 -

if (Backbone.history.fragment === 'foo') {
    Backbone.history.loadUrl(Backbone.history.fragment);
 } else {
     router.navigate('foo', {'trigger': true});
}

感谢@dankantor的绝妙技巧!

如果您确实必须执行此用例(以强制重新加载同一页面/哈希),您是否不想使用 Backbone.history.getFragment() 而不是 history.fragment 这样您就不会访问历史的属性? 看起来更干净。

我创建了一个 Backbone.history.refresh 方法来强制重新加载。 然后,在某些项目中,无论哈希值是否更改,我都会覆盖默认导航行为以重新加载:

      _.extend(Backbone.History.prototype, {
            refresh: function() {
                this.loadUrl(this.fragment);
            }
        });

        var routeStripper = /^[#\/]/;
        var origNavigate = Backbone.History.prototype.navigate;
        Backbone.History.prototype.navigate = function (fragment, options) {
            var frag = (fragment || '').replace(routeStripper, '');
            if (this.fragment == frag)
                this.refresh();
            else
                origNavigate.call(this, fragment, options);
        };
此页面是否有帮助?
0 / 5 - 0 等级

相关问题

g00fy- picture g00fy-  ·  9评论

miguelpayet picture miguelpayet  ·  9评论

sarkasm picture sarkasm  ·  7评论

cueedee picture cueedee  ·  3评论

azizZaben picture azizZaben  ·  5评论