×

EmberJS 教程

EmberJS 概述EmberJS 环境配置EmberJS 应用EmberJS 对象模型EmberJS 模板EmberJS 路由器EmberJS 组件EmberJS 模型EmberJS 视图EmberJS 控制器EmberJS 测试EmberJS 指定查询参数

Ember 对象模型

Ember 类的定义 初始化 继承Ember 类的扩展Ember 计算属性Ember 观察者Ember 数据绑定Ember 枚举Ember 第一章对象模型小结

Ember handlebars模板

Ember handlebars基础Ember handlebars条件表达式Ember handlebars遍历标签Ember handlebars显示对象键Ember handlebars属性绑定Ember {{link-to}} 助手Ember 路由 模板执行渲染顺序Ember {{action}} 助手Ember 表单元素Ember 调试助手Ember 工具类的助手Ember 第二章模板小结

Ember 路由

Ember 路由定义Ember 指定与路由关联的模型Ember 模板渲染Ember 路由重定向Ember 路由终止挑战和激活Ember loading error子路由Ember 查询参数Ember 异步路由

Ember 组件

Ember 组件定义Ember 属性传递Ember 包裹内容自定义包裹组件的HTML标签Ember 处理事件Ember action触发变化

Ember 控制器

Ember 控制器Ember 管理控制器的依赖关系

Ember 模型

Ember model简介Ember 定义模型Ember 记录查询Ember 新建、更新、删除记录Ember 设置记录到StoreEmber model的关联关系处理Ember 元数据Ember 自定义适配器Ember 自定义序列号器

Ember 测试

Ember 测试简介Ember 验收测试Ember 单元测试

Ember 路由定义


当你的应用启动的时候,路由器就会匹配当前的URL到你定义的路由上。然后按照定义的路由层次逐个加载数据、设置应用程序状态、渲染路由对应的模板。

1,基本路由

app/router.jsmap方法里定义的路由会映射到当前的URL。当map方法被调用的时候方法体内的route方法就会创建路由。

下面使用Ember CLI命令创建两个路由:

ember generate route about
ember generate route favorites

命令执行完之后你可在你的项目目录app/routes下面看到已经创建好的两个路由文件已经app/templates下面路由对应的模板文件。 此时在app/router.jsmap方法中已经存在了刚刚创建的路由配置。这个是Ember CLI自动为你创建了。

// app/router.js

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.route('about');
  this.route('favorites');
});

export default Router;

现在分别修改app/templates下面的两个模板文件如下:


这个是about模板!<br>
{{outlet}}

这个是favorites模板!<br>
{{outlet}}

然后访问http://localhost:4200/about或者http://localhost:4200/favorites,如果你的程序没有问题你也会得到如下显示结果:

run result

如果你觉得favorites这个路由名字太长是否可以修改成其他名字呢?答案是肯定的,你只要修改router.jsmap方法的配置即可。

Router.map(function() {
  this.route('about');
  // 注意:访问的URL可以写favs但是项目中如果是使用route的地方仍然是使用favorites
  this.route('favorites', { path: '/favs' });
});

此时访问:http://localhost:4200/favs,界面显示的结果与之前是一样的。

说明:默认情况下访问的URL与路由名字是一致的,比如this.route('about')this.route('about', { path: ‘/about’ })是同一个路由,如果URL与路由不同名则需要使用{path: '/xxx'}设置映射的URL。

在handlebars模板中可以使用{{link-to}}助手在不同的路由间切换,使用时需要在link-to助手内指定路由名称。比如下面的代码使用link-to助手实现在aboutfavs两个路由间切换。 为了页面能美观一点引入bootstrap,使用npm命令安装:bower install bootstrap,如果安装成功你可以在bower_components目录下看到 bootstrap相关的文件。安装成功之后引入到项目中,修改chapter3_routes/ember-cli-build.js。在return语句前加入如下两行代码(作用就是引入 bootstrap 框架):

app.import("bower_components/bootstrap/dist/css/bootstrap.css");
app.import("bower_components/bootstrap/dist/js/bootstrap.js");

修改application.hbs,增加一个导航菜单。


    <div class="container-fluid">
            <div class="navbar-header" href="#">

                {{#link-to 'index' class="navbar-brand"}}Home{{/link-to}}
            </div>
            <ul class="nav navbar-nav">
                <li>{{#link-to 'about'}}about{{/link-to}}</li>
                <li>{{#link-to 'favorites'}}favorites{{/link-to}}</li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Login</a></li>
                <li><a href="#">Logout</a></li>
            </ul>
    </div>

<div class="container-fluid" style="margin-top: 70px;">

{{outlet}}
</div>

如果看到页面没有bootstrap效果请重新启动项目。如果运行项目后再浏览器控制台出现如下错误。

run result

如果出现上图错误需要在config/environment.js中加上一些安全策略设置代码,有关设置的解释请看下面网址的文章介绍。

  1. ember-cli-and-content-security-policy-cs
  2. https://www.w3.org/TR/2015/CR-CSP2-20150721/
    , contentSecurityPolicy: {
      'default-src': "'none'",
      'script-src': "'self' 'unsafe-inline' 'unsafe-eval' use.typekit.net connect.facebook.net maps.googleapis.com maps.gstatic.com",
      'font-src': "'self' data: use.typekit.net",
      'connect-src': "'self'",
      'img-src': "'self' www.facebook.com p.typekit.net",
      'style-src': "'self' 'unsafe-inline' use.typekit.net",
      'frame-src': "s-static.ak.facebook.com static.ak.facebook.com www.facebook.com"
    }

配置截图

上图是我的演示项目配置。然后点击about会得到如下界面

result

可以看到浏览器地址栏的URL变为about了,并且页面显示的内容也是about模板的内容。同理你点击favorites地址栏就变为http://localhost:4200/favs并且显示的内容是favorites的(为什么URL是favs而不是favorites呢,因为前面已经修改了route和URL的映射关系,路由favorites对应的URL是favs)。 上述演示的就是路由的切换!!!

可以看到浏览器地址栏的URL变为about了,并且页面显示的内容也是about模板的内容。同理你点击“favorites”地址栏就变为http://localhost:4200/favs并且显示的内容是favorites的(为什么URL是favs而不是favorites呢,因为前面已经修改了route和URL的映射关系,路由favorites对应的URL是favs)。 上述演示的就是路由的切换!!!

2,路由嵌套

还记得在前面的Ember.js 入门指南之十三{{link-to}} 助手这篇文章的内容吗?在这篇文章中比较详细的介绍了路由的嵌套与怎么使用嵌套的路由。不妨回过头去看看。在这里打算就不讲了……如果有不明白的请看官网的教程。

3,application路由

application路由是默认的路由,是程序的入口,所有其他自定义的路由都先进过application才到自定义的路由。并且application路由对应的application.hbs模板是所有自定义模板的父模板,所有自定义的模板都会渲染到application.hbs模板的{{outlet}}上。有关于路由的执行顺序以及模板的渲染顺序在前面的Ember.js 入门指南之十三{{link-to}} 助手也讲过了,在此也不打算在做过多的介绍了。你可以回头看之前的文章或者到官网查看。

4,index路由

对于所有的嵌套的路由,包括最顶层的路由Ember会自动生成一个访问URL为/对应路由名称为index的路由。

比如下面的两种路由设置是等价的。

//  app/router.js
// ……

Router.map(function() {
    this.route('about');
    // 注意:访问的URL可以写favs但是项目中如果是使用route的地方仍然是使用favorites
    this.route('favorites', { path: '/favs' });
});

export default Router;
//  app/router.js
// ……

Router.map(function() {
    this.route('index', { path: '/' });
    this.route('about');
    // 注意:访问的URL可以写favs但是项目中如果是使用route的地方仍然是使用favorites
    this.route('favorites', { path: '/favs' });
});

export default Router;

index路由会渲染到application.hbs模板的{{outlet}}上。这个是Ember默认设置。当用户访问/about时Ember会把index模板替换为about模板。

对于路由嵌套的情况也是如此。

//  app/router.js
//  ……
Router.map(function() {

    this.route('posts', function() {
        this.route('new');
    });

});

export default Router;
//  app/router.js

//  ……
Router.map(function() {
    this.route('index', { path: '/' });
    this.route('posts', function() {
        this.route('index', { path: '/' });
        this.route('new');
    });

});

export default Router;

两种设置方式都会得到如下图的路由表。打开浏览器的“开发者工具”点开“Ember”选项卡,在点开“/#Routes”你就可以看到如下路由表(显示是顺序有可能跟你的不一样)。

路由渲染结果

注:loadingerror这两个路由是ember自动生成的,他们的用法会在后面的文章介绍。

当用户访问/posts时实际进入的路由是posts.index对应的模板是posts/index.hbs,但是实际中我并没有创建这个模板,因为Ember默认把这个模板渲染到posts.hbs{{outlet}}上。由于这个模板不存在也就相当于什么都没做。当然你也可以创建这个模板。
使用命令:ember generate template posts/index然后在这个模板中添加以下显示的内容:


<h2>这里是/posts/index.hbs。。。</h2>

再此访问http://localhost:4200/posts,是不是可以看到增加的内容了。

你可以这么理解对于每一个有子路由的路由都有一个名为index的子路由并且这个路由对应的模板为index.hbs,如果把有子路由的路由当做一个模块看待那么index.hbs就是这个模块的首页。特别是做过一些信息系统的朋友应该是很熟悉的,基本上没个子模块都会有一个首页,这个首页现实的内容就是一进入这个模块时就显示的内容。既然是子模板当然也不会例外它也会渲染到父模板的{{outlet}}上。比如上面的例子当用户访问http://localhost:4200/posts实际进入的是http://localhost:4200/posts/(后面多了一个/,这个/对应的模板就是index),当用户访问的是http://localhost:4200/posts/new,那么进入的就是posts/new.hbs这个模板(也是渲染到posts.hbs{{outlet}}上)。

4,动态段

关于动态段在前面的Ember.js 入门指南之十三{{link-to}} 助手也介绍过了,在这里就再简单补充下。

路由最主要的任务之一就是加载model

例如对于路由this.route('posts');会加载项目中所有的posts下的model。但是当你只想加载其中一个model的时候怎么处理呢?而且大多数情况我们是不需要一次性加载完全部数据的,一般情况都是加载其中一小部分。这个时候就需要动态段了!

动态段以:开头,并且后面接着modelid属性。

//  app/router.js

//  ……

Router.map(function() {
    this.route('about');
    // 注意:访问的URL可以写favs但是项目中如果是使用route的地方仍然是使用favorites
    // this.route('favorites', { path: '/favs' });

    this.route('posts', function() {
        this.route('post', { path: '/:post_id'});
    });

});

export default Router;

此时你可以访问http://localhost:4200/posts/1,不过我们还没创建model所以会报错。这个我们暂时不管,后面会有一章是介绍model的。现在只要知道你访问http://localhost:4200/posts/1就相当于获取id值唯一的model

5,通配符/全局路由

Ember也同样运行你使用*作为URL通配符。有了通配符你可以设置多个URL访问同一个路由。

this.route('about', { path: '/*wildcard' });

然后访问:http://localhost:4200/wildcard或者访问http://localhost:4200/2423432ffasdfewildcard或者http://localhost:4200/2333都是可以进入到about这个路由,但是http://localhost:4200/posts仍然进入的是posts这个路由。因为可以匹配到这个路由。

6,重置子路由的命名空间

在有路由嵌套的情况下,一般情况我们访问URL的格式都是父路由名/子路由名,Ember提供了一个resetNamespace:true选项可以用户重置子路由的命名空间,使用这个设置的路由可以直接这样访问/子路由名,不需要写父路由名。

this.route('posts', function() {
    this.route('post', { path: '/:post_id'});
    this.route('comments', { resetNamespace: true}, function() {
        this.route('new');
    });
});

此时如果你想问的new这个路由你可以直接不写commentshttp://localhost:4200/posts/new,而不需要http://localhost:4200/posts/comments/new,不过模板渲染的顺序没变,new模板仍然是渲染到comments{{outlet}}上。

不过个人觉得还是不使用这个设置比较好,特别是在开发的时候你可以看到访问的URL的层次,对你调试代码还是很有帮助的。

以上的内容就是定义路由的全部内容。都是非常重要的知识,希望你能好好掌握,对于路由的嵌套请看之前的文章。如果有疑问请给我留言或者访问官网看原教程。


分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)