当用户浏览我们的租赁信息列表的时候,他们可能会想要有一些交互性的操作来帮助他们做出决定。让我们为每一条租赁信息添加切换图片大小的能力。为了完成它,我们将使用一个组件。
让我们生成一个 rental-listing
组件,它将管理我们每一条租赁信息的行为。每个组件都需要一个破折号来避免和一个潜在的 HTML 元素发生冲突,所以 rental-listing
是可取的而 rental
不可取。
ember g component rental-listing
Ember CLI 随后将为我们的组件生成数个文件
installing component
create app/components/rental-listing.js
create app/templates/components/rental-listing.hbs
installing component-test
create tests/integration/components/rental-listing-test.js
我们将从为我们想要的图片切换行为安装一个失败测试开始。
为了我们的联合测试,我们将创建一个租赁信息存根,它将拥有我们 rental 模型所有的属性。我们可以预见组件将在没有 wide
类的情况下被初次渲染。点击图片将添加 wide
类到我们的元素上,然后点击它第二次将去掉其 wide
类型。注意我们通过使用 CSS 选择器 .image
来查找图片元素。
tests/integration/components/rental-listing-test.js
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';
moduleForComponent('rental-listing', 'Integration | Component | rental listing', {
integration: true
});
test('should toggle wide class on click', function(assert) {
assert.expect(3);
let stubRental = Ember.Object.create({
image: 'fake.png',
title: 'test-title',
owner: 'test-owner',
type: 'test-type',
city: 'test-city',
bedrooms: 3
});
this.set('rentalObj', stubRental);
this.render(hbs`{{rental-listing rental=rentalObj}}`);
assert.equal(this.$('.image.wide').length, 0, 'initially rendered small');
this.$('.image').click();
assert.equal(this.$('.image.wide').length, 1, 'rendered wide after click');
this.$('.image').click();
assert.equal(this.$('.image.wide').length, 0, 'rendered small after second click');
});
一个组件包含两个部分:
- 一个定义界面的模板(
app/templates/components/rental-listing.hbs
) - 一个定义行为的 JavaScript 源文件(
app/components/rental-listing.js
)。
我们全新的 rental-listing
组件将管理租赁信息的用户界面和用户交互。一开始,让我们将展现单条租赁信息的详细内容从 rentals.hbs
模板移动到 rental-listing.hbs
模板,并且添加图片内容:
app/templates/components/rental-listing.hbs
<article class="listing">
<img src="{{rental.image}}" alt="">
<h3>{{rental.title}}</h3>
<div class="detail owner">
<span>Owner:</span> {{rental.owner}}
</div>
<div class="detail type">
<span>Type:</span> {{rental.type}}
</div>
<div class="detail location">
<span>Location:</span> {{rental.city}}
</div>
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{rental.bedrooms}}
</div>
</article>
在我们的 rentals.hbs
模板中,让我们用新的 rental-listing
组件替代 {{#each}}
循环中陈旧的 HTML 标记:
app/templates/rentals.hbs
<div class="jumbo">
<div class="right tomster"></div>
<h2>Welcome!</h2>
<p>
We hope you find exactly what you're looking for in a place to stay.
</p>
{{#link-to 'about' class="button"}}
About Us
{{/link-to}}
</div>
{{#each model as |rentalUnit|}}
{{rental-listing rental=rentalUnit}}
{{/each}}
这里,我们通过其名字引入了 rental-listing
组件,并且将每一个 rentalUnit
分配为了 rental
组件的属性。
隐藏和显示图片
现在,我们可以添加当用户请求时显示租赁信息图片的功能。
当 isWide
被设置成 true时,让我们使用 {{#if}}
helper,通过将元素的类名设置成 wide
来将我们当前租赁信息图片显示得更大一些。我们也将添加一些文字来表明图片可以被点击,并用锚元素(a 标签)包装它们,为其添加 image
这个类名,使得我们的测试程序可以找到它。
app/templates/components/rental-listing.hbs
<article class="listing">
<a class="image {{if isWide "wide"}}">
<img src="{{rental.image}}" alt="">
<small>View Larger</small>
</a>
<h3>{{rental.title}}</h3>
<div class="detail owner">
<span>Owner:</span> {{rental.owner}}
</div>
<div class="detail type">
<span>Type:</span> {{rental.type}}
</div>
<div class="detail location">
<span>Location:</span> {{rental.city}}
</div>
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{rental.bedrooms}}
</div>
</article>
isWide
的值取自于我们组件的 JavaScript 文件,即此时的 rental-listing.js
。既然我们想要图片一开始展示得小一点,我们将设置这个值一开始为 false
:
app/components/rental-listing.js
import Ember from 'ember';
export default Ember.Component.extend({
isWide: false
});
为了让用户可以放大图片,我们将需要添加一个切换 isWide
值的行为。让我们将这个行为命名为 toggleImageSize
app/templates/components/rental-listing.hbs
<article class="listing">
<a {{action 'toggleImageSize'}} class="image {{if isWide "wide"}}">
<img src="{{rental.image}}" alt="">
<small>View Larger</small>
</a>
<h3>{{rental.title}}</h3>
<div class="detail owner">
<span>Owner:</span> {{rental.owner}}
</div>
<div class="detail type">
<span>Type:</span> {{rental.type}}
</div>
<div class="detail location">
<span>Location:</span> {{rental.city}}
</div>
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{rental.bedrooms}}
</div>
</article>
点击锚元素将把这个行为发送到组件中。Ember 随后将进入到 actions
哈希并且调用 toggleImageSize
函数。
让我们为我们的组件创建 toggleImageSize
函数和切换 isWide
属性。
app/components/rental-listing.js
import Ember from 'ember';
export default Ember.Component.extend({
isWide: false,
actions: {
toggleImageSize() {
this.toggleProperty('isWide');
}
}
});
现在,当我们点击浏览器中的图片或者 View Larger
链接时,我们会发现我们的图片变得更大了。当我们再次点击图片,我们将看到它变得更小了。