ember.js101 入门教程 第八课 (全课完)

桂飞翼
2023-12-01

到目前为止,我们一直在使用硬编码数据,这通常是不现实的。大多数的时间,你有一些 REST 或实时数据需要与后端同步;Ember Data 可以帮助我们了。我已经得到了一个地址簿应用程序的。左边的是我们的联系人列表,当被点击时,我们会显示右边的联系人。在这一集里,我们将看到如何Ember Data 可以帮助我们填充列表-创建和编辑。
我已经得到了一个地址簿应用程序的框架。左边的是我们的联系人列表,当被点击时,我们会显示右边的联系人。在这一集里,我们将看到如何Ember Data可以帮助我们填充-创建和编辑列表项。

所有八次课程的英文视频下载在链接:http://pan.baidu.com/s/1bo2HEdp 密码:lbx0;分享给大家。

Ember Data

首先让我们创建数据仓库:

App.Store = DS.Store.extend({
  revision: 12,
  adapter: DS.RESTAdapter.create({
    url: 'http://addressbook-api.herokuapp.com'
  })
});

该仓库是您和数据仓库之间的主要接口。当你获取和访问数据时,它本质上是一个对象台账。该适配器负责将仓库请求转换为对持久层采取适当的动作。我们使用默认的REST适配器,因此它将Contact.find(1)自动转换为一个Ajax请求/contacts/1 。理想情况下,您可以不用更改任何其他应用程序代码来更换适配器。

App.Contact = DS.Model.extend({
  first: DS.attr('string'),
  last: DS.attr('string'),
  avatar: DS.attr('string'),
  github: DS.attr('string'),
  notes: DS.attr('string')
});

model 模型

我们得到了所有这些字符串属性的联系模型。我们让DS.attr模型知道这些属性,并能够持久化到我们的数据仓库。

最后,我们可以把Contact信息插入路由的模型钩子。

App.ApplicationRoute = Ember.Route.extend({
  model: function() {
    return App.Contact.find();
  }
});

App.ContactRoute = Ember.Route.extend({
  model: function(params) {
    return App.Contact.find(params.contact_id);
  }
});

就像我们的应用程序的是有生命的。你可能想知道其中的细节,是从一个服务器获取资源,这是一个异步操作。
Contact.find(1)总是返回一个模型。它会发送请求,但立即返回一个空属性模型。由于我们的模板是绑定到模型数据,它将填充的模型属性,尽快向服务器请求数据。这不需要考虑任何的动作。
任何已被调用的模型的后续调用将返回同一个对象作为第一个调用。一旦服务器已作出回应,就不再需要访问服务器了。这使得应用程序真正有效。因为在contactroute模型钩是如此普遍,我们甚至不需要它,ember有默认的约定。

它怎么知道?

你可能非常想知道ember是如何知道网址的。Ember对象的toString方法返回相当聪明的信息 restadapter使用它来构建传统的URL。

App.Contact.toString()
'App.Contact'

让我们再看一下代码。非常令人难以置信的是,我们用这么少的代码中得到这么多的功能。

完整代码:

<!DOCTYPE html>
<!--
Created using JS Bin
http://jsbin.com

Copyright (c) 2016 by symphonyh (http://jsbin.com/doricu/1/edit)

Released under the MIT license: http://jsbin.mit-license.org
-->
<meta name="robots" content="noindex">
<html>
<head>
<meta name="description" content="ED: Reading" />
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0-rc.4/handlebars.js"></script>
  <script src="http://builds.emberjs.com.s3.amazonaws.com/ember-1.0.0-rc.4.js"></script>
<script src="http://builds.emberjs.com.s3.amazonaws.com/ember-data-0.13.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
<style id="jsbin-css">
/* @override http://localhost:8000/css/app.css */

/* @override http://localhost:8000/css/app.css */

body {
  font-family: sans-serif;
  background: #fff;
}

#master {
  position: absolute;
  left: 0;
  width: 200px;
  top: 0;
  bottom: 0;
  border-top: 1px solid #888;
}

#detail {
  position: absolute;
  left: 200px;
  right: 0;
  top: 0;
  bottom: 0;
  border-left: 1px solid #b4b4b4;
  border-top: 1px solid #888;
  overflow: auto;
}

.welcome {
  padding: 20px;
  text-align: center;
}

#master ul {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

#master a {
  display: block;
  padding: 4px 8px;
  text-decoration: none;
  color: inherit;
  font-size: 14px;
  background: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#master a:hover {
  background: #fcfcfc;
}

#master a.active {
  background: #3875d7;
  color: #fff;
}

#master li {
  border-bottom: 1px solid #e0e0e0;
}

#master header {
  font-size: 12px;
  text-align: center;
  padding: 2px;
  border-bottom: 1px solid #aaa;
  color: #666;
  background-color: #ffffff;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#eeeeee));
  background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee);
  background-image:    -moz-linear-gradient(top, #ffffff, #eeeeee);
  background-image:      -o-linear-gradient(top, #ffffff, #eeeeee);
  background-image:         linear-gradient(to bottom, #ffffff, #eeeeee);

}

#master ul {
  position: absolute;
  top: 19px;
  left: 0;
  right: 0;
  bottom: 43px;
  overflow: auto;
}

#controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 4px;
  border-top: 1px solid #aaa;

  background-color: #ffffff;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#eeeeee));
  background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee);
  background-image:    -moz-linear-gradient(top, #ffffff, #eeeeee);
  background-image:      -o-linear-gradient(top, #ffffff, #eeeeee);
  background-image:         linear-gradient(to bottom, #ffffff, #eeeeee);
}

.contact-data dt,
.contact-header .avatar {
  width: 30%;
  text-align: right;
  color: #888;
}

.contact-data dt label {
  display: inline-block;
  padding: 4px;
}

.contact-data input[type=text],
.contact-data textarea {
  font-family: inherit;
  font-size: inherit;
  border: 1px solid transparent;
  padding: 2px;
  width: 80%;
  outline: none;
}

.contact-data input[type=text]:hover,
.contact-data textarea:hover {
  border-color: #ccc;
}

.contact-data input[type=text]:focus,
.contact-data textarea:focus {
  border-color: #9cbaeb;
}

.contact-data textarea {
  height: 150px;
  padding: 4px 2px;
}

.contact-data dd,
.contact-header h1 {
  width: 65%;
}

.contact-data dt,
.contact-data dd,
.contact-header h1,
.contact-header .avatar {
  display: inline-block;
  vertical-align: top;
  margin: 0;
  padding: 0;
}

.contact-header h1 {
  font-size: 18px;
}

.contact-header img {
  max-width: 64px;
  height: 64px;
}

.contact-header {
  margin-top: 55px;
}

.contact-data a {
  margin-left: 4px;
  color: #3875d7;
  text-decoration: none;
}

.contact-data a:hover {
  color: #d79d38;
}


.btn {
  display: inline-block;
  padding: 4px 10px 4px;
  font-size: 16px;
  line-height: 20px;
  color: #333333;
  text-align: center;
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
  vertical-align: middle;
  background-color: #f5f5f5;
  background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
  background-image: linear-gradient(top, #ffffff, #e6e6e6);
  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
  border: 1px solid #cccccc;
  border-color: #ccc #ccc #888;
  border-bottom-color: #b3b3b3;
  border-radius: 4px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  background-repeat: repeat-x;
}

.btn:hover,
.btn:active,
.btn.active,
.btn.disabled,
.btn[disabled] {
  background-color: #e6e6e6;
  *background-color: #d9d9d9;
}

.btn:hover {
  color: #333333;
  text-decoration: none;
  background-color: #e6e6e6;
  *background-color: #d9d9d9;
  background-position: 0 -15px;
}

.btn.active,
.btn:active {
  background-color: #e6e6e6;
  background-image: none;
  outline: 0;
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
}

.btn.disabled,
.btn[disabled] {
  cursor: default;
  background-color: #e6e6e6;
  background-image: none;
  opacity: 0.65;
  box-shadow: none;
}


.pull-right {
  float: right;
}

</style>
</head>
<body>
  
  <script type="text/x-handlebars">
  <nav id="master">
    <header>
      All Contacts ({{controller.length}})
    </header>
  
    <ul>
      {{#each controller}}
      <li>
        {{#linkTo "contact" this}}
          {{first}} {{last}}
        {{/linkTo}}
      </li>
      {{/each}}
    </ul>
    
    <div id="controls">
      <button class="btn">+</button>
      <button class="btn pull-right">-</button>
    </div>
  </nav>
  
  <div id="detail">
    {{outlet}}
  </div>
  </script>
 
  <script type="text/x-handlebars" id="index">
  <div class="welcome">
    <h2>Address Book</h2>
  </div>
  </script>
  
  <script type="text/x-handlebars" id="contact">
  <header class="contact-header">
    <div class="avatar">
      <img {{bindAttr src="avatar"}}>
    </div>
  </header>

  <dl class="contact-data">
    <dt><label for="contact-first">First Name</label></dt>
    <dd>{{input value=first id="contact-first"}}</dd>

    <dt><label for="contact-last">Last Name</label></dt>
    <dd>{{input value=last id="contact-last"}}</dd>

    <dt><label for="contact-avatar">Avatar URL</label></dt>
    <dd>{{input value=avatar id="contact-avatar"}}</dd>

    <dt><label for="contact-github">Github</label></dt>
    <dd>
      {{input value=github id="contact-github"}}
      {{#if github}}
      <br><a {{bindAttr href="github"}}>view ➚</a>
      {{/if}}
    </dd>

    <dt><label for="contact-twitter">Twitter</label></dt>
    <dd>
      {{input value=twitter id="contact-twitter"}}
      {{#if twitter}}
      <br><a {{bindAttr href="twitter"}}>view ➚</a>
      {{/if}}
    </dd>

    <dt><label for="contact-notes">Notes</label></dt>
    <dd>{{textarea value=notes id="contact-notes"}}</dd>
  </dl>
  </script>
<script id="jsbin-javascript">
var App = Ember.Application.create();

App.Store = DS.Store.extend({
  revision: 12,
  adapter: DS.RESTAdapter.create({
    url: 'http://addressbook-api.herokuapp.com'
  })
});

App.Contact = DS.Model.extend({
  first: DS.attr('string'),
  last: DS.attr('string'),
  avatar: DS.attr('string'),
  github: DS.attr('string'),
  twitter: DS.attr('string'),
  notes: DS.attr('string')
});

App.Router.map(function() {
  this.resource('contact', {path: '/contact/:contact_id'});
});

App.ApplicationRoute = Ember.Route.extend({
  model: function() {
    return App.Contact.find();
  }
});


</script>
</body>
</html>

转载于:https://www.cnblogs.com/cloudhan/p/5467138.html

 类似资料: