单击浏览器后退按钮时,嵌套路由渲染到相同的模板/出口中断 [英] Nested routes rendering into same template/outlet breaks on browser back button click

查看:10
本文介绍了单击浏览器后退按钮时,嵌套路由渲染到相同的模板/出口中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌套的路由层次结构,我的应用程序需要它来跟踪用户模型选择.我正在尝试使用主应用程序模板,并将每个路由渲染到该模板上的单个出口中.这在我从父级到子级向下遍历路由层次结构时起作用.

I have a nested route hierarchy that I need for my application to track user model selections. I'm trying to use a main application template and have each route render into a single outlet on that template. This works as I traverse down the route hierarchy from parent to child.

但是,一旦您单击浏览器后退按钮返回路由层次结构,父路由 renderTemplate 钩子就不会触发.这会导致孩子从插座上脱钩,并且没有任何东西重新回到插座中.

However once you click the browser back button to go back up the route hierarchy the parent route renderTemplate hook doesn't fire. This results in the child being unhooked from the outlet and nothing rendered back into it.

这是一个例子:

App = Ember.Application.create({});

App.Router.map(function(){
    this.resource("animals", function(){
        this.resource("pets", function(){
              this.route('new')
        })
    })
});
App.PetsView = Ember.View.extend({
    templateName : 'wild/pets'
});
App.AnimalsRoute = Ember.Route.extend({
     renderTemplate: function() {
    this.render({
    into: "application",
    outlet : "A"
})
     }});
App.PetsRoute = Ember.Route.extend({
     renderTemplate: function() {
this.render({
    into: "application",
    outlet : "A"
})}});

App.PetsNewRoute = Ember.Route.extend({
     renderTemplate: function() {
this.render({
    into: "application",
    outlet : "A"
})}});

使用模板:

<script type="text/x-handlebars" data-template-name="application">
    <h1>{{#linkTo "animals"}}Hello from Ember.js</h1>{{/linkTo}}
      {{outlet A}}
</script>

<script type="text/x-handlebars" data-template-name="animals">
    {{#linkTo "pets"}}This is animals list{{/linkTo}}
</script>
<script type="text/x-handlebars" data-template-name="wild/pets">
    {{#linkTo "pets.new"}}This is pets list{{/linkTo}}
</script>

<script type="text/x-handlebars" data-template-name="pets/new">
    This is pet creation
</script>

这里有一个带有这段代码的 jsfiddle.单击链接以遍历路由,然后单击浏览器后退按钮,应用程序模板将在其出口中没有挂钩的情况下呈现.

And here's a jsfiddle with this code. Click the links to traverse the routes, then click the browser back button and the application template is rendered with nothing hooked into its outlet.

http://jsfiddle.net/Wq6Df/3/

有什么办法可以强制重新渲染,还是我的方法不对?

Is there any way to force a re-render, or am I going about this the wrong way?

推荐答案

你的做法是错误的.

Ember 依赖于匹配路由层次结构的嵌套出口的层次结构.因此,每次单击将您带到子路由的链接时,子路由都应该渲染到其父模板中的插座中.如果您总是渲染到相同的模板和出口,那么当您返回路线层次结构时,Ember 将无法正确更新出口.(我希望这是有道理的.)

Ember depends on a hierarchy of nested outlets that match the route hierarchy. So every time you click on a link that takes you to a child route, the child route should render into an outlet within its parent's template. If you always render into the same template and outlet, then Ember won't be able to update the outlets properly when you move back up the route hierarchy. (I hope that makes sense.)

为了避免这个问题,一个好的经验法则是只使用 into 选项来呈现您在路由层次结构之外管理的模板.例如,我使用它来呈现没有 URL 并且我手动拆除的模态视图.在视图层次结构中,您几乎总是可以避免使用 into.例如,如果您需要使用单独的控制器渲染多个模板,则可以在模板中使用 {{render}} 助手,而不是在您的模板中调用 render路线.

To avoid this problem, a good rule of thumb is to only use the into option for rendering templates that you're managing outside of the route hierarchy. For example, I use it for rendering modal views that don't have a URL and which I tear down manually. Within the view hierarchy, you can almost always avoid using into. For example, if you need to render more than one template with a separate controller, you can use the {{render}} helper within your template instead of calling render in your route.

在这种情况下,最简单的解决方案可能是将您的路由嵌套与模板嵌套相匹配.您的 animals/index 路线和 pets 是真正的兄弟姐妹,而不是父子,对于 pets/list 和您的 pets/新的.事实上,这是默认但有点隐藏的行为:你真的应该使用 pets/index 来呈现列表而不是父 pets 路由.

In this case, the easiest solution is probably to match your route nesting to your template nesting. Your animals/index route and pets are really siblings, not parent-child, and same for pets/list and your pets/new. In fact, this is the default but somewhat hidden behaviour: you should really be using pets/index to render the list instead of the parent pets route.

App = Ember.Application.create({});

App.Router.map(function(){
    this.resource("animals", function(){
        // this.route("index"); at path /animals is implicit
        this.resource("pets", function(){
              // this.route("index"); at path /animals/pets is implicit
              this.route("new")
        })
    })
});

// You don't really need any of these route definitions now;
// I'm including them for clarity
App.AnimalsRoute = Ember.Route.extend();
App.AnimalsIndexRoute = Ember.Route.extend();

App.PetsRoute = Ember.Route.extend();
App.PetsIndexRoute = Ember.Route.extend();
App.PetsNewRoute = Ember.Route.extend();

// Not sure why you need to use a custom template name here, 
// but it should work fine
App.PetsView = Ember.View.extend({
    templateName : 'wild/pets'
});

使用模板:

<!-- animals gets rendered into this outlet -->
<script type="text/x-handlebars" data-template-name="application">
    <h1>{{#linkTo "animals"}}Hello from Ember.js</h1>{{/linkTo}}
    {{outlet}}
</script>

<!-- animals/index and pets get rendered into this outlet -->
<script type="text/x-handlebars" data-template-name="animals">
    {{outlet}}
</script>

<!-- no outlet here because animals/index has no child routes -->
<script type="text/x-handlebars" data-template-name="animals/index">
    {{#linkTo "pets"}}This is animals list{{/linkTo}}
</script>

<!-- pets/index and pets/new get rendered into this outlet -->
<script type="text/x-handlebars" data-template-name="wild/pets">
    {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="pets/index">
    {{#linkTo "pets.new"}}This is pets list{{/linkTo}}
</script>

<script type="text/x-handlebars" data-template-name="pets/new">
    This is pet creation
</script>

这篇关于单击浏览器后退按钮时,嵌套路由渲染到相同的模板/出口中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆