点燃圣火! Ember.js 的初学者指南

转自:http://www.adobe.com/cn/devnet/html5/articles/flame-on-a-beginners-guide-to-emberjs.htmlcss

做者 Andy Matthews

如今,处处均可以看到复杂的 JavaScript 应用程序。 因为这些应用程序变得愈来愈复杂,一长串的 jQuery 回调语句,或者经过应用程序在各个点执行不一样的函数调用,这些都变得没法再让人接受。 这致使了 JavaScript 开发人员了解到传统的软件程序员已经知道了几十年的问题: 组织和效率很是重要,而且能够对应用程序的性能是否优异产生重大影响。 html

实现组织和效率的其中一个最经常使用的架构模式,被称为 Model View Controller (缩写为 MVC) 。 这种模式鼓励开发人员将其应用程序的不一样部分分割为更易于管理的块。 您没必要使用一个函数直接调用数据库,您能够建立了一个 Model(模型)来为您管理数据库。 您没必要使用一个布满输出和逻辑语句的 HTML文件,一个简单的模板或 View(视图)就能够您简化显示代码。 最后,Controller(控制器)管理您的应用程序的流,帮助各类零散的部件更高效地互相沟通。 在您的应用程序中使用这个模式,能够更轻松地增长新的功能。 html5

做为最近爆发的基于 Internet 的软件开发的一部分,出现了一堆使人眼花缭乱的 MVC 框架,好比 Ember.js、Backbone.js、Knockout.js、Spine.js、Batman.js 和 Angular.js。 一方面是初级和中级开发人员,另外一方面是骨灰级程序员,以 JavaScript 编写并针对 JavaScript 开发而设计的这些库补充了这二者之间的空白。 它们提供多种特性和功能,根据开发人员的需求知足技能水平各异的不一样开发人员。 jquery

在本教程中,您将经过构建一个可用的 Twitter 时间轴查看器,更熟悉 Ember.js。 ios

Ember.js 简介

Ember.js 是 JavaScript 框架包中最新的成员之一。 它演变出了最初于 2007 年建立的 SproutCore 项目,Apple 在包括 MobileMe 在内的各类 web 应用程序中大量使用了该项目。 在 emberjs.com,Ember 被形容为 "一个 JavaScript 框架,用于建立能够消除样板并提供标准应用程序架构的大型 web 应用程序。" 它自己紧密集成了名为 Handlebars 的模板引擎,该引擎为 Ember 提供了其中一个最强大的功能: 双向数据绑定。 Ember 还提供了其余功能,好比状态管理(某个用户状态是已注销仍是已登陆)、自动更新模板(当底层数据发生变化时,您的 UI 也一样发生变化)以及计算属性 (firstName + lastName = fullName)。 Ember 通过一年可靠的开发后,已经成为一个强大的参与者。 git

Ember 只有一个依赖项—jQuery。 Ember 应用程序的样板 HTML 设置看起来应该与下面的代码相似。 请注意,jQuery 和 Ember 都从 CDN(内容交付网络)进行更新。 若是用户在早些时候访问须要这些文件的其余网站时已经下载过这些文件,这会加快用户的页面加载速度。 程序员

<html>
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.6.min.js"></script>
    <script src="js/app.js"></script>
</head>
<body>
</body>
</html>
定义 MVC

在您继续本教程以前,更明确地定义 MVC 可能会是一个好主意。 这个概念在 1979 年已经出现,自那时以来,该模式已经出现一些不一样的变体。 最多见的流程一般是这样的: github

  1. 用户执行一个操做,好比敲击键盘或单击鼠标按钮。
  2. 控制器接收输入并触发一个消息给模型。
  3. 模型根据消息修改其内容(删除一行或更新购物车数量)。
  4. 视图监视模型中的变动,并相应地更新用户界面。

了解 MVC 模式的工做方式,可使您的应用程序流动变得更简单。 此外,因为代码被分割成不一样的块,开发人员团队可以更轻松地协同工做,且不互相干扰。 web

Ember 如何执行 MVC

JavaScript 是一个灵活而强大的语言,但它也有不足之处。 它不提供那种使本身适合于 MVC 风格开发的开箱即用的功能。 所以 Ember 利用一批额外功能扩展了该基本语言。 在构建 Ember 应用程序时,您会使用四个主要部件: Application(应用程序)、Model(模型)、View(视图)和 Controller(控制器)。 如下各节将回顾每一个部件。 ajax

Application(应用程序)

每一个 Ember 应用程序都须要一个 Ember.Application 实例。这是代码其他全部部分的基础,它提供有用的功能,以及名称空间(对应用程序的其他部件进行分组的一种方式)。 定义一个 Ember 应用程序很简单:

Songs = Ember.Application.create({
    mixmaster: 'Andy'
});

该代码定义一个名为 Songs 的应用程序,将其名为 mixmaster 的属性设置为 Andy 。 您能够将应用程序的名称改成您喜欢的任何名称,但 Ember 要求变量的名称以一个大写字母开始,以便绑定的系统能够找到它。 在建立应用程序时还能够添加其余内置选项,而且您也能够添加任意的属性或方法,但初学者用户主要关心的多是ready() 方法。 该方法的工做方式与 jQuery 的 document.ready() 块彻底同样,而且可以经过如下方式实现:

Songs = Ember.Application.create({
    mixmaster: 'Andy',
    totalReviews: 0,
    ready: function(){
        alert('Ember sings helloooooooooo!');
    }
});
Models(模型)

若是没有数据,应用程序就没有意义。 Ember 使用 Models 帮助开发人员以结构化的方式管理数据。 除了保存数据以外,Ember Models 也对其内部的数据进行建模。 换句话说,若是您想储存有关 MP3 集合的信息,您的模型可能包含一个标题属性、一个艺术家眷性和一个流派属性等。 该模型可能看起来以下所示:

Songs.Song = Ember.Object.extend({
    title: null,
    artist: null,
    genre: null,
    listens: 0
});

关于这几行代码,还有几件事情要注意。

  • 您立刻就能够看到您的应用程序在使用的名称空间。 Songs 是应用程序的名称,而 Song 是模型的名称。
  • 当扩展对象时,您是在为此模型的将来实例建立蓝图。 由于这是主对象,全部歌曲将以它为基础,因此它使用一个大写字母。 这些命名约定使得您在未来能够更轻松地分辨正在使用的对象类型。
  • 在建立模型时,您能够为每一个属性提供默认值。 titleartistgenre 属性可在之后填写,因此被标记为 null (或无)。 listens 属性默认为 0 ,而且它的值将在您听音乐收藏时增长。

如今, Song 模型已到位,您能够添加第一首歌曲。 您使用了 extend 来初始化 Song 模型,但您将使用create 来添加它的一个实例。 下面是它的样子:

mySong = Song.create({
    title: 'Son of the Morning',
    artist: 'Oh, Sleeper',
    genre: 'Screamo'
});

请注意,变量没有以一个大写字母开始,那是由于它是 Song 模型的一个实例。 新的歌曲也不在 Songs 名称空间中。 您将几乎再也不须要在您的应用程序中建立模型的实例。 您这样作固然没问题,但通常来讲,您会将模型的每一个实例放置在相近对象的较大集合中,好比 ArrayController(后面会详细介绍)。

Views(视图)

在一个 Ember 应用程序或任何 MVC 风格的应用程序中,View(视图)是用户能够看见并与之交互的组件。 经过将原始 HTML 直接添加到页面,能够定义一个内联模板。 该模板将被包含在 script 标记中。 您能够将它添加到页面中您但愿显示内容的任意位置。

<script type="text/x-handlebars">
    Hello <b>{{Songs.mixmaster}}</b>
</script>

请注意, script 标记的类型是 text/x-handlebars 。 这使 Ember 在加载页面时,有一些东西能够抓取。 Ember 自动准备在这个脚本标记内所包含的任何 HTML,以便在您的应用程序中使用。 将这几行代码放在您的应用程序中,就会显示如下文本:

Hello <b>Andy</b>

在继续以前,先深刻了解一下。 在您的浏览器中,右键单击粗体文本,并使用浏览器的开发工具检查它。 您可能注意到一些额外的元素。 为了知道在一个基本的属性发生变化时,要更新哪一部分的 HTML,Handlebars 将插入带有惟一 ID 的标记元素;例如:

<b>
    <script id="metamorph-0-start" type="text/x-placeholder"></script>
    Andy
    <script id="metamorph-0-end" type="text/x-placeholder"></script>
</b>

您能够直接在 JavaScript 中定义一个视图,而后使用视图辅助程序将它显示到页面中。 Ember 有通用视图,能够在应用程序中建立简单的 div 标记,但它还配有预打包的一组视图,用于构建基本控件,好比文本输入框、复选框和选择列表。 从在 JavaScript 文件中定义简单的 TextArea 视图开始。

Songs.ReviewTextArea = Ember.TextArea.extend({
    placeholder: 'Enter your review'
});

而后,经过引用包含该视图的变量的、以单词 view 开头的路径,将它显示到页面。 运行下面的代码,在您的浏览器中显示 TextArea 字段,其占位符文本为 "Enter your review"。 您也能够在定义中指定 rowscols 做为额外的属性。

<script type="text/x-handlebars">
    {{view Songs.ReviewTextArea}}
</script>
Handlebars

如今,您可能想知道代码中的 {{}} 表示什么,咱们正好能够谈谈 Handlebars,也称为 mustaches。 稍微思考一下,您就会明白它们为何被称为 Handlebars pard'ner。 Handlebars 是一个模板引擎,让开发人员能够混合原始 HTML 和 Handlebars 表达式 ,生成渲染的HTML。 表达式以 {{ 开始,并以 }} 结束。 如前所述,全部模板必须放在类型为 text/x-handlebarsscript 标记内。

默认状况下,handlebars 内所包含的任何值据称都会绑定到它的值。 这意味着,若是由于应用程序内的一些其余操做使该值发生变化,显示给用户的值也将更新。 考虑如下代码:

<script type="text/x-handlebars">
    My songs have {{Songs.totalReviews}} reviews.
</script>

第一次初始化您的应用程序时,用户将看到如下文本。

My songs have 0 reviews.

可是,凭借数据绑定,随着因更新 Songs.totalReviews 而添加的更多评论,该值将实时改变。

Handlebars 还经过使用 {{#if}}{{else}} . 支持流控制。 这些元素使您能够根据应用程序中的值实现模板的条件化 。 您能够修改前面的示例,在没有任何评论时向用户显示另外一条消息:

<script type="text/x-handlebars">
    {{#if Songs.totalReviews}}
        Read all my reviews!
    {{else}}
        There are no reviews right now.
    {{/if}}
</script>

若是在应用程序的生命周期中的任意时点, Songs.totalReviews 值发生了变化,该视图将更新并显示另外一部分的消息。 值得注意的还有, #/ 符号只是为了告诉 Handlebars,这个特定的视图辅助程序有一个闭合标记。

Controllers(控制器)

此前,Model(模型)被定义为一种使开发人员可以管理数据的方法。 这没错,但这只是一种狭义的定义。 一个模型只包含与单一事物有关的数据;例如,一首歌曲(但不是多首歌曲)或一我的(但不是多我的)。 当您想管理多个相同类型的数据块时,您须要一个 Controller(控制器)。 有了 Ember,您可使用 ArrayController 来管理多组歌曲、人员、部件或任何东西。 每一个 ArrayController 都有内置的 content 属性,用于存储数据。 该数据能够是简单的字符串,也能够是复杂的值,好比数组或对象。 此外,ArrayController 中包含的函数能够用于与在 ArrayController 中所包含的数据进行交互。 您的 Song 集合的 ArrayController 看起来会是什么样呢?

Songs.songsController = Ember.ArrayController.create({
    content: [],
    init: function(){
        // create an instance of the Song model
        var song = Songs.Song.create({
            title: 'Son of the Morning',
            artist: 'Oh, Sleeper',
            genre: 'Screamo'
        });
        this.pushObject(song);
    }
});

init 函数不是必需的,但它很方便,由于 songsController 一旦就绪,就会触发 init 函数。 它能够用来将现有数据填充到控制器,在本例中,您将使用它来将一首歌曲添加到控制器中,以演示 Ember 的数据绑定。 添加以前的 ArrayController 定义和如下内联模板,并在您的浏览器中运行代码:

<script type="text/x-handlebars">
    {{#each Songs.songsController}}
        <h3>{{title}}</h3>
        <p>{{artist}} - {{genre}}</p>
    {{/each}}
</script>

Handlebars each 辅助程序收到一组数据的路径,而后对它进行循环。 与控制器中每一项分别匹配的各个 each块中的一切都将显示在页面上。 请注意,您没有提供直接访问内容数组的路径,由于就 Ember 而言,控制器 就是 数组。所生成的 HTML 输出以下所示:

<h3>Son of the Morning</h3>
<p>Oh, Sleeper - Screamo</p>
全面整合: EmberTweets

此时,您应该已较好地了解了 Ember 是什么,以及它能够作什么。您也应该了解使 Ember 实现其能力的每一个组件: Application(应用程序)、Model(模型)、View(视图)和 Controller(控制器)。 如今是时候应用这些知识了,以编写一个真实可用的应用程序。 您将跳过行业标准的 "todo 应用程序" ,并转移到对许多人来讲更亲近和熟悉的: Twitter。 在本教程的剩余部分,您将构建一个 Twitter 时间轴查看器。 在编写任何代码以前, 看看最终结果可能会有帮助。

建立样板文件

使用本文开头的样板 HTML 页面,您将首先构建基础 HTML。 复制下面的代码,并粘贴到一个名为 index.html 的新 HTML 文件中。您须要引用在本文的示例文件中的 CSS 文件。 示例文件还包含了这个项目的起点,也能够供您随时使用。

<!doctype html>
<html>
<head>
    <title>Tweets</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.6.min.js"></script>
    <script src="app.js"></script>
</head>
<body>
    <script type="text/x-handlebars">
        <div id="frm">
            <b>Load Tweets for: </b>
        </div>
        <div id="content">
            <div id="recent">
                <h3>Recent Users</h3>
            </div>
            <div id="tweets">
                <h3>Tweets</h3>
            </div>
        </div>
    </script>
</body>
</html>

您能够看到这个应用程序有三个部分: 一个输入字段,容许用户输入一个 Twitter 用户名;时间轴查看器,显示所选 Twitter 用户的 tweet;以及最新的用户列表,它将存储之前的搜索。

搜索框将出如今页面顶部,最新的用户在左侧的栏中,而 tweet 自己将占据页面右侧的绝大部分版面。

下一步,建立名为 app.js 的另外一个文件,并添加如下内容。 这些注释能够帮助您保持代码的条理性。 在您的浏览器中加载此页面,并确保没有任何错误。

/**************************
* Application
**************************/

/**************************
* Models
**************************/

/**************************
* Views
**************************/

/**************************
* Controllers
**************************/
应用程序初始化

您须要作的第一件事,是初始化您的应用程序。 直接在标记为 Application 的注释块下面,放入如下代码:

App = Em.Application.create();

请注意,此行使用的不是 Ember.Application,而是 Em.Application。在可能要使用 "Em" 任何地方,您均可以使用 "Ember",Ember 团队经过加入这个方便的快捷方式,减小了要输入的字数。

接下来,您将添加 TextInput 视图和提交按钮。 直接在标记为 "Views" 的注释块下面,放入如下代码:

App.SearchTextField = Em.TextField.extend({
    insertNewline: function(){
        App.tweetsController.loadTweets();
    }
});

此块从使用 App 名称空间开始,而后扩展 Ember 的其中一个预打包的视图 TextField。 除了在 Views 内容许任意属性和函数以外,Ember 也提供了内置的辅助函数。 那就是 insertNewLine() 函数;每当光标在输入框中,而且用户在键盘上按 Enter/Return 键时,就会执行该函数。

建立模板块

如今已定义了 TextField View,您将要添加相应的视图辅助代码到 HTML 文件中。 切换到 index.html 并在显示为 "Load Tweets for" 的行后面直接添加如下代码。 请记住, {{}} 内的任何代码都是模板,而且将被 Ember 用于输出数据。 此外,任何以单词 view 开始的模板指的都是已经在您的 JavaScript 代码中定义过的视图。

{{view App.SearchTextField placeholder="Twitter username" valueBinding="App.tweetsController.username"}}
<button {{action "loadTweets" target="App.tweetsController"}}>Go!</button>

这部分的模板包含一个视图辅助程序,以及一个带有 {{action}} 辅助程序的按钮标记。 TextField ViewSearchTextField 以占位符文本开始,占位符文本是内置在 HTML5 文本输入字段中的一个属性。 若是该字段为空, placeholder 属性中的文本将被放进输入字段。 当有人开始输入时,该值将消失。 Ember 使开发人员能够在其内置视图内使用任何 HTML 5 标准属性。

第二个属性突出显示 Ember 数据绑定的能力。 Ember 使用一组约定来帮助它肯定您想完成什么。 视图(一个模板或一个 JavaScript 文件中的视图)中以单词 "Binding" (注意大写字母)结尾的任何属性,自动为它前面的属性设置绑定。 在本例中,Ember 将 App.tweetsController.username 的值绑定到输入字段的 value 属性。 每当变量的内容发生变化,输入字段中的值将自动更新,反之亦然。

{{action}} 使得更易于将功能添加到输入驱动的元素。 它有两个选项: 操做名称和目标。 二者综合起来,造成一个 "路径" ,指向 Ember 对象中所包含的函数。 在上面按钮的示例中, "路径" 将是App.tweetsController.loadTweets() ,当用户在文本字段内按 Enter 键时,也会调用相同的函数。 在您的浏览器中加载 index.html,并单击提交按钮,或在输入字段内按 Enter 键。 若是您查看浏览器控制台,您就会看到一个错误。 这是由于尚未定义 App.tweetsController

准备 Tweet 存储对象

如今是定义 App.tweetsController 的好时机。 在 app.js 中的 Controllers 注释块后面添加如下代码。您应该已经熟悉如下代码。 名称空间、ArrayController、内容数组 —— 一切都在。 但此次您将会添加一个任意属性 (username ) 和一个函数 ( loadTweets )。 在添加 ArrayController 以后,从新加载您的浏览器。 在输入框中输入一个单词,而后单击按钮。 您会获得一个提示框,回显您所键入的单词。 您能够随时删除提示行。 您还将看到一个错误,代表还没有定义 addUser 方法。

App.tweetsController = Em.ArrayController.create({
    content: [],
    username: '',
    loadTweets: function() {
        var me = this;
        var username = me.get("username");
        alert(username);
        if ( username ) {
            var url = 'http://api.twitter.com/1/statuses/user_timeline.json'
                url += '?screen_name=%@&callback=?'.fmt(me.get("username"));
            // push username to recent user array
            App.recentUsersController.addUser(username);
        }
    }
});

仔细看看 loadTweets 函数的定义;它有一些陌生的代码。 第一行为函数的其他部分设置一个 范围 。 根据定义,范围或 this 对于全部 Ember 对象来讲都是当前函数,在本例中是 App.tweetsController 。 可是,在本教程中,稍后您能够将更多功能添加到 loadTweets 函数。 如今设置当前范围,有助于 Ember 理解您正在使用的上下文。

如前所述,Ember 提供了许多辅助函数,使编写应用程序变得更容易,这些函数包括 get()set() 。 这两个函数内置在每一个 Ember 对象中,并提供对任何属性或函数的快速访问。 下一行使用当前对象App.tweetsController 的范围,而后调用 get() 函数,将您但愿获取其值的属性的名称传递进去。 您可能会好奇,在开始时要使用的用户名的值从哪里来。 请记住,Ember 的数据绑定是双向的。 这意味着,一旦您在输入字段中键入了一个值,该输入字段视图的 valueBinding 属性就会用一个值更新 App.tweetsController对象。

检索到用户名后,会运行一个测试,以确保它不是空的。 此时 if 块内只有两个语句,但这在之后会更改。 第一个语句为一个用户将 URL 设置到 Twitter 的 JSON 文件。 您可能没有立刻注意到这里有什么特殊之处,但仔细再看看,您就会发现末尾的 %@.fmt().fmt() 函数执行一个方便的字符串替换,使用 %@ 做为标记。 因为应用程序的设计要求存储搜索列表,所以您必须以某种方式存储您的搜索字词。 最后一行执行该函数,将用户名的值推送到 App.recentUsersController ArrayController。 由于该对象还没有存在,因此运行代码将产生一个错误。

存储以前的搜索

在下面这一节中,您将建立用于存储最近搜索的对象。 使用如下代码并将它添加到 App.tweetsController对象后面。

App.recentUsersController = Em.ArrayController.create({
    content: [],
    addUser: function(name) {
        if ( this.contains(name) ) this.removeObject(name);
        this.pushObject(name);
    },
    removeUser: function(view){
        this.removeObject(view.context);
    },
    searchAgain: function(view){
        App.tweetsController.set('username', view.context);
        App.tweetsController.loadTweets();
    },
    reverse: function(){
        return this.toArray().reverse();
    }.property('@each')
});

您已经熟悉了如何建立 ArrayController 和添加一个空的内容数组,但该对象有一些新的元素,它们以 addUser函数开始。 这将使用名称为 contains() 的内置 Ember 函数检查现有数组 ( this )。 若是它找到一个结果,它会使用 ArrayController 的函数 removeObject() 删除该结果。 与该函数相反,有一个名为 pushObject() 的函数,它用于将单独的对象添加到内容数组。 这两个函数都有处理多个对象的复数版本: pushObjects()removeObjects() 。 此代码在添加搜索词以前首先删除现有搜索词,那么相同的搜索词就不会被屡次显示。 既然您已经知道如何从内容数组中删除一个对象, removeUser() 函数中惟一的新元素就是参数。 当使用{{action}} 辅助程序调用一个函数时,Ember 隐式传递一个引用给当前视图。 在 App.tweetsController 的示例中,视图有一个上下文,这基本上是当前被遍历的项。 该上下文用于从数组中删除选定的项。

searchAgain() 函数也将当前视图接收为一个参数。 当用户单击以前搜索过的字词,该函数会用选定的用户名填充 App.tweetsController.username ,而后触发 loadTweets() 函数,为前面的搜索提供一个单击视图。

默认状况下,Ember 按升序将内容显示到页面。 数组索引 1 是第一个,数组索引 2 是第二个,依次类推。 此应用程序的设计要求按降序显示最近的搜索。 这意味着该数组必须被逆转。 虽然这不是内置函数,但您能够看到要添加它是多么容易。 Reverse() 首先使用 Ember toArray() 函数将 Ember 内容数组转换成一个普通的数组,逆转它,而后返回它。 使得该函数能够被用做一个数据源的,是在末尾添加的 property() 函数。property() 函数使用一个指定函数所要求的以逗号分隔的属性列表。 在本例中, property() 函数隐式地使用内容数组自己,使用 @each 依赖键对该数组内每一个元素进行寻址。 在下一节中,您将看到如何实施reverse() 函数。

显示以前的搜索

如今,您已存储了以前的搜索,是时候将它们显示在页面上。 复制如下模板,并将它添加到标签为 Recent Usersh3 标记后面。

<ol>
    {{#each App.recentUsersController.reverse}}
        <li>
            <a href="#" title="view again" {{action "searchAgain" target="App.recentUsersController"}}>{{this}}</a> - 
            <a href="#" title="remove" {{action "removeUser" target="App.recentUsersController"}}>X</a>
        </li>
    {{/each}}
</ol>

如今,您应该已经熟悉全部这些代码。 each 块指向内容数组,它内部所包含的 HTML 将被应用到App.recentUsersController 变量中的每一项。 没必要显式指向内容数组,但在本例中,该代码指向 reverse函数,它以反序提供数据。 {{action}} 辅助程序让用户单击每一个锚标记,并触发指定的函数。 可能不太熟悉的惟一一个元素是 {{this}} 。 当遍历内容数组时,Ember 在 {{this}} 变量中保存对当前索引的引用。 由于每一项的值都只是一个字符串,您可使用 {{this}} 直接输出当前项的值。 单击 Twitter 用户名,将再次加载该用户的 tweet,而单击这些 tweet 的名称则将从 recentUsersController 删除它们。

加载 tweet

保存搜索词没问题了,但实际执行搜索又如何呢? 接下来,您将添加从 Twitter 检索 JSON 包的片断,并将它显示到页面。 使用如下 Ember Model 并直接将它添加到标签为 Model 的注释块后面。 请记住,Ember Model 是它们将包含的数据是一个蓝图。

App.Tweet = Em.Object.extend({
    avatar: null,
    screen_name: null,
    text: null,
    date: null
});

在 app.js 中,找到显示为 App.recentUsersController.addUser(username); 的代码行;并在它后面直接添加如下代码:

$.getJSON(url,function(data){
    me.set('content', []);
    $(data).each(function(index,value){
        var t = App.Tweet.create({
            avatar: value.user.profile_image_url,
            screen_name: value.user.screen_name,
            text: value.text,
            date: value.created_at
        });
        me.pushObject(t);
    })
});

若是您之前使用过 jQuery,您可能已经使用过 .get() 函数来检索数据。 .getJSON() 函数作一样的事情,只是它将 JSON 包视做一个结果。 此外,它使用返回的 JSON 字符串,并将它转换成可执行的 JavaScript 代码。 数据被检索到以后,内容数组被清空,删除全部现有的 tweet。 下一行提取数据包,并将它封装在一个 jQuery 对象中,所以 .each() 方法能够循环所生成的 Tweets。 在 each 块中,使用数据填充了 Tweet Model 的一个副本,而后将其推送到 ArrayController。

最后,您须要将如下显示代码添加到 index.html。直接复制并粘贴它到标签为 Tweetsh3 标记后面。

<ul>
    {{#each App.tweetsController}}
        <li>
            <img {{bindAttr src="avatar"}} />
            <span>{{date}}</span>
            <h3>{{screen_name}}</h3>
            <p>{{text}}</p>
        </li>
    {{/each}}
</ul>

Ember 使用纯 {{Handlebars}} 能够很容易地输出数据到页面,但有一个问题。 还记得 Ember 如何在脚本标记中包装输出的值吗? 当您使用 HTML 属性时,这并非一个选项。 因此 Ember 提供 {{bindAttr}} 辅助程序。 在这个辅助程序内放置的任何属性都将如常输出,但仍保留绑定。 继续进行操做,如今运行您的应用程序。 输入一个用户名,会看到 Tweets 出现。

下一步阅读方向

在本文中,您学习了 Ember.js 功能的基础知识。 您也学习了 Ember 如何使用其Models、Views、Controllers,固然还有 Application 对象实施 MVC。 您使用 Handlebars 经过视图辅助程序和操做辅助程序建立了模板。 您学习了如何使用 Models 建立数据的蓝图,使用 Controllers 将该数据存储在集合集,并使用 Views 将数据显示到页面。 最后,您使用了 Ember 来构建一个具备数据绑定、计算属性和自动更新模板的完整应用程序。 您的母亲将为您感到自豪!

有关 Ember 的更多读物,请查看如下的一些连接:

本文基于Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License协议发布。

相关文章
相关标签/搜索