×

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 loading、error子路由


在前面的Ember.js 路由定义提过loadingerror子路由,它们是Ember默认创建的,并在beforeModelmodelafterModel这三个回调执行完毕之前会先渲染当前路由的loadingerror模板。

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

对于上述的路由设置Ember会生成如下的路由列表:

路由映射图

每个路由都会自动生成一个loadingerror路由,下面我将一一演示这两个路由的作用。 图片前面loadingerror路由对应的application路由。posts_loadingposts_error对应的是posts路由。

1,loading子状态

Ember建议数据放在beforeModelmodelafterModel回调中获取并传递到模板显示。但是只要是加载数据就需要时间,对于Ember应用来说,在model等回调中加载完数据才会渲染模板,如果加载数据比较慢那么用户看到的页面就是一个空白的页面,用户体验很差!

Ember提供的解决办法是:在beforeModelmodelafterModel回调还没返回前先进入一个叫loading的子状态,然后渲染一个叫routeName-loading的模板(如果是application路由则对应的直接是loadingerror不需要前缀)。

为了演示这效果在app/templates下创建一个posts-loading模板。如果程序正常,在渲染模板posts之前会先渲染这个模板。


<img src="assets/images/loading/loading.gif" />

然后修改路由posts.js,让model回调执行时间更长一些。

//  app/routes/posts.js

import Ember from 'ember';

export default Ember.Route.extend({

    model: function() {
        //  模拟一个延时操作,
        for (var i = 0; i < 10000000;i++) {

        }
        return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');
    }
});

执行http://localhost:4200/posts,首先会看到执行的loading模板的内容,然后才看到真正要显示的数据。有一个加载过程,如下面2幅图片所示。

图1

图2

2,loading事件

beforeModelmodelafterModel回调没有立即返回之前,会先执行一个名为loading的事件。

//  app/routes/posts.js

import Ember from 'ember';

export default Ember.Route.extend({

    model: function() {
        //  模拟一个延时操作,
        for (var i = 0; i < 10000000;i++) {

        }
        return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');
    },
    actions: {
        loading: function(transition, originRoute) {
            alert("Sorry this is taking so long to load!!");
        }
    }
});

页面刷新后会弹出一个提示框,先不点击“确定”。打开浏览器的“开发者 -> 开发者工具”,切换到Network标签下。找到“pulls”这个请求,点击它。

result

从图中可以看到此时model回调并没有返回。此时响应的内容是空的,说明loading事件实在model回调返回之前执行了。

然后点击弹出框的“确定”,此时可以看到Response有数据了。说明model回调已经执行完毕。 注意:如果当前的路由没有显示定义loading事件,这个时间会冒泡到父路由,如果父路由也没有显示定义loading事件,那么会继续向上冒泡,一直到最顶端的路由application

3,error子状态

loading子状态类似,error子状态会在beforeModelmodelafterModel回调执行过程中出现错误的时候触发。

命名方式与loading子状态也是类似的。现在定义一个名为posts-error.hbs的模板。


<p style="color: red;">
posts回调解析出错。。。。
</p>

然后在model回调中手动添加一个错误代码。

//  app/routes/posts.js

import Ember from 'ember';

export default Ember.Route.extend({

    model: function() {
        //  模拟一个延时操作,
        for (var i = 0; i < 10000000;i++) {

        }
        var e = parseInt(value);
        return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');
    }
});

注意var e = parseInt(value);这句代码,由于value没有定义所以应该会报错。那么此时页面会显示什么呢??

result

如果你的演示程序没有其他问题那么你也会得到上图的结果。但是如果没有定义这个模板,那么界面上将是什么都不显示。

如果你想在xxx-error.hbs模板上看到是什么错误信息,你可以在模板上打印model的值。如下:


<p style="color: red;">
posts回调解析出错。。。。
<br>
{{model}}
</p>

此时页面会显示出你的代码是什么错误。

result

不过相比于浏览器控制台打印的错误信息简单很多!!!

4,error事件

error事件与第一点讲的loading事件也是相似的。使用方式与loading一样。个人觉得这个事件非常有用,我们可以在这个事件中根据error状态码的不同执行不同的逻辑,比如跳转到不同的路由上。

//  app/routes/posts.js

import Ember from 'ember';

export default Ember.Route.extend({

    model: function() {
        return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls____');
    },

    actions: {
        error: function(error, transition) {
            console.log('error = ' + error.status);
            //  打印error对象里的所有属性和方法名
            for(var name in error){         
               console.log(name); 
               // console.log('属性值或者方法体==》' + error[name]);
            }    
            alert(names); 
            if (error && error.status === 400) {
                return this.transitionTo("about");
            } else if (error.status === 404) {
                return this.transitionTo("form");
            } else {
                console.log('else......');
            }
        }
    }
});

注意getJSON方法里的URL,我在URL后面随机加了一些字符,目的是让这个URL不存在。此时请求应该会找不到这个地址error的响应码应该是404。然后直接跳转到form这个路由上。 运行http://localhost:4200/posts之后,浏览器控制台打印信息如下:

result

页面也会跳转到form

result

到此路由加载数据过程中涉及的两个状态loadingerror的内容全部介绍完,这两个状态在优化用户体验方面是非常有用的,希望想学习Ember的同学好好掌握!!!=^=


分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)