当用户浏览我们的租赁信息列表的时候,他们可能会想要有一些交互性的操作来帮助他们做出决定。让我们为每一条租赁信息添加切换图片大小的能力。为了完成它,我们将使用一个组件。
让我们生成一个 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> <p class="detail owner"> <span>Owner:</span> {{rental.owner}} </p> <p class="detail type"> <span>Type:</span> {{rental.type}} </p> <p class="detail location"> <span>Location:</span> {{rental.city}} </p> <p class="detail bedrooms"> <span>Number of bedrooms:</span> {{rental.bedrooms}} </p> </article>
在我们的 rentals.hbs 模板中,让我们用新的 rental-listing 组件替代 {{#each}} 循环中陈旧的 HTML 标记:
app/templates/rentals.hbs
<p class="jumbo"> <p class="right tomster"></p> <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}} </p> {{#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> <p class="detail owner"> <span>Owner:</span> {{rental.owner}} </p> <p class="detail type"> <span>Type:</span> {{rental.type}} </p> <p class="detail location"> <span>Location:</span> {{rental.city}} </p> <p class="detail bedrooms"> <span>Number of bedrooms:</span> {{rental.bedrooms}} </p> </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> <p class="detail owner"> <span>Owner:</span> {{rental.owner}} </p> <p class="detail type"> <span>Type:</span> {{rental.type}} </p> <p class="detail location"> <span>Location:</span> {{rental.city}} </p> <p class="detail bedrooms"> <span>Number of bedrooms:</span> {{rental.bedrooms}} </p> </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 链接时,我们会发现我们的图片变得更大了。当我们再次点击图片,我们将看到它变得更小了。