在Ember中路由和模板的执行都是有一定顺序的,它们的顺序为:主路由->子路由1->子路由2->子路由3->……。模板渲染的顺序与路由执行顺序刚好相反,从最后一个模板开始解析渲染。
注意:模板的渲染是在所有路由执行完之后,从最后一个模板开始。关于这一点下面的代码会演示验证,官网教程有介绍,点击查看。
比如有一路由格式为application/posts/detail/comments/comment
,此时路由执行的顺序为:application/posts
-> detail
-> comments
-> comment
,application
是项目默认的路由,用户自定义的所有路由都是application
的子路由(默认情况下),相对应的模板也是这样,所有用户自定义的模板都是application.hbs
的子模板。如果你要修改模板的渲染层次你可以在route
中重写renderTemplate
回调函数,在函数内使用render
方法指定要渲染的模板(如:render(other)
,渲染到other
这个模板上)更多有关信息请查看这里。并且它们对应的文件模板结构如下图:
路由与模板是相对应的,所以模板的目录结构与路由的目录结构是一致的。
你有两种方式构建上述目录:
comment.js
使用命令:ember generate route posts/detail/comments/comment
,Ember CLI会自动为我们创建目录和文件。创建好目录结构之后我们添加一些代码到每个文件。运行项目之后你就会一目了然了……。
下面我按前面讲的路由执行顺序分别列出每个文件的内容。
// app/routes/posts.js
import Ember from ember;
export default Ember.Route.extend({
model: function() {
console.log(running in posts...);
return { id: 1, routeName: The route is posts};
// return Ember.$.getJSON(https://api.github.com/repos/emberjs/ember.js/pulls);
}
});
import Ember from ember;
export default Ember.Route.extend({
model: function(params) {
console.log(params id = + params.post_id);
console.log(running in detail....);
return { id: 1, routeName: The route is detail.. };
}
});
// app/routes/posts/detail.js
import Ember from ember;
export default Ember.Route.extend({
model: function(params) {
console.log(params id = + params.post_id);
console.log(running in detail....);
return { id: 1, routeName: The route is detail.. };
}
});
// app/routes/posts/detail/comments.js
import Ember from ember;
export default Ember.Route.extend({
model: function() {
console.log(running in comments...);
return { id: 1, routName: The route is comments....};
}
});
// app/routes/posts/detail/comments/comment.js
import Ember from ember;
export default Ember.Route.extend({
model: function(params) {
console.log(params id = + params.post_id);
console.log(running in comment...);
return { id: 1, routeName: The route is comment...};
}
});
下面是模板各个文件的内容。其列出才顺序与路由的顺序一致。
{{model.routeName}} >> {{outlet}}
{{model.routeName}} >> {{outlet}}
{{model.routeName}} >> {{outlet}}
{{model.routeName}} >> {{outlet}}
下图是路由执行的顺序,并且在执行的过程中渲染路由对应的模板。
从上图中可用清楚的看到当你运行一个URL时,与URL相关的路由是怎么执行的。
application
),此时进入到路由的model
回调方法,并且返回了一个对象{ id: 1, routeName: The route is application... }
,执行完回调之后继续转到子路由执行直到最后一个路由执行完毕,所有的路由执行完毕之后开始渲染页面。detail.js
和comments.js
。在代码中加入一个模拟休眠的操作。
// app/routes/posts/detail.js
import Ember from ember;
export default Ember.Route.extend({
model: function(params) {
console.log(params id = + params.post_id);
console.log(running in detail….);
// 执行一个循环,模拟休眠
for (var i = 0; i < 10000000000; i++) {
}
console.log(The comment route executed...);
return { id: 1, routeName: The route is detail.. };
}
});
```javascript
// app/routes/posts/detail/comments.js
import Ember from ember;
export default Ember.Route.extend({
model: function(params) {
console.log(params id = + params.post_id);
console.log(running in comment...);
// 执行一个循环,模拟休眠
for (var i = 0; i < 10000000000; i++) {
}
return { id: 1, routeName: The route is comment...};
}
});
刷新页面,注意查看控制台输出信息和页面显示的内容。
新开一个窗口,执行URL:http://localhost:4200/posts/2/comments。
控制台输出到这里时处理等待(执行for
循环),此时已经执行了两个路由application
和posts
,并且正在执行detail
,但是页面是空白的,没有任何HTML元素。
在detail
路由执行完成之后转到路由comments
。然后执行到for
循环模拟休眠,此时页面仍然是没有任何HTML元素。然后等到所有route
执行完毕之后,界面才显示model
回调里设置的信息。
每个子路由设置的信息都会渲染到最近一个父路由对应模板的{{outlet}}
上面。
comment
comment
渲染完成”comment
最近的父模板comments
comment
渲染完成 comments
渲染完成”comments
最近的父模板detail
comment
渲染完成 comments
渲染完成 detail
渲染完成”detail
最近的父模板posts
comment
渲染完成 comments
渲染完成 detail
渲染完成 posts
渲染完成”posts
最近的父模板application
comment
渲染完成 comments
渲染完成 detail
渲染完成 posts
渲染完成 application
渲染完成”只要记住一句话:子模板的都会渲染到父模板的{{outlet}}
上,最终所有的模板都会被渲染到application
的{{outlet}}
上。
博文完整代码放在Github(博文经过多次修改,博文上的代码与github代码可能又出入,不过影响不大!),如果你觉得博文对你有点用,请在github项目上给我点个star
吧。您的肯定对我来说是最大的动力!!