惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

Katz Got Your Tongue

Polaris: What I'm Working On Why Ember is Different: Running Browser Tests in a Browser Exploring Ember Polaris: CSS Modules Without Addons Exploring Ember Polaris: A Fresh Take on the Component Format Ember Octane: Airtable Time Ember Octane: Pulling Out Data Ember Octane: Let's Go "We're the Together Framework" Together: The Merb Story #EmberJS2019 More Accessible Than Ever Fun With PowerShell: Let's Get Started (Digging Deeper) PowerShell, Deduplicating Records PowerShell: Let's Get Started Fun with PowerShell: Installation
Ember Octane: Components
Yehuda Katz · 2020-03-27 · via Katz Got Your Tongue

This post is the second in a series on building an Ember application HTML-first. In this series, we're going to build the EmberConf schedule application from the ground up.

  1. Let's Go
  2. Components ← This post
  3. Pulling Out Data
  4. Airtable Time
  5. Cleaning Things Up
  6. Adding More Pages
  7. Polishing: Server-Side Rendering, Prerendering and Code Splitting
Here's what we built in the last post.

In the last post, we created a website for a conference schedule and deployed it.

But there's quite a bit of duplication in the HTML that we wrote. We have three copies of the same HTML, and if we flesh it out to describe the entire schedule, there will be a massive amount of duplication. Whenever we make small changes to the HTML structure, we'll have to change a ton of copies.

Let's take a look at the HTML for the FastFlood talk:

<li class="event">
  <div class="time">
    <p>10:45am</p>
    <p>11:15am</p>
  </div>
  <h1>FastFlood: The Story of a Massive Memory Leak in FastBoot Land</h1>
  <h2>
    <ul>
      <li>Sergio Arbeo</li>
    </ul>
  </h2>
  <ul class="images">
    <li><img src="https://emberconf.com/assets/images/people/sergio-arbeo.jpg"></li>
  </ul>
</li>

And the Paradigm Shift talk:

<li class="event">
  <div class="time">
    <p>11:30am</p>
    <p>12:00pm</p>
  </div>
  <h1>Octane: A Paradigm shift in EmberJS</h1>
  <h2>
    <ul>
      <li>Suchita Doshi</li>
    </ul>
  </h2>
  <ul class="images">
    <li><img src="https://emberconf.com/assets/images/people/suchita-doshi.jpg"></li>
  </ul>
</li>

These two chunks of HTML look really similar. Most of the content is the same, but there are a few spots where the talks are different.

1. Remove Duplication With Components

You can visualize the two snippets of HTML this way. The black boxes show the few places where the HTML for each talk is different.

The HTML for the two talks is very similar, with some small differences, identified by black boxes.

What we want is the ability to create a "template" for our talks. A template is kind of like Madlibs. Most of the details stay the same, but there are a few spots that can change each time it's used.

Madlibs

In Ember, a component is kind of like a custom HTML tag that looks a lot like like black box diagram we showed above.. Put this snippet of HTML in app/components/event.hbs.

<li class="event">
  <div class="time">
    <p>{{@start}}</p>
    <p>{{@end}}</p>
  </div>
  <h1>{{@title}}</h1>
  <h2>
    <ul>
      <li>{{@speaker}}</li>
    </ul>
  </h2>
  <ul class="images">
    <li>
      <img src="https://emberconf.com/assets/images/people/{{@image}}.jpg">
    </li>
  </ul>
</li>

The variables in an Ember component are described by surrounding them in {{ and prefixing the variable name with @. A variable is a part of the component that can change (vary).

Now that we defined our component, we can use it in application.hbs.

<Event
  @title="FastFlood: The Story of a Massive Memory Leak in FastBoot Land"
  @start="10:45am"
  @end="11:15am"
  @speaker="Sergio Arbeo"
  @image="sergio-arbeo"
/>

<Event
  @title="Octane: A Paradigm shift in EmberJS"
  @start="11:30am"
  @end="12:00pm"
  @speaker="Suchita Doshi"
  @image="suchita-doshi"
/>

Because the component was defined in app/components/event.hbs, we use it as <Event>. We fill in the variables by specifying them just like HTML attributes, but with the @ prefix,  which tells us that they're variables.

2. Lists

If you're paying close attention, you probably noticed that we weren't able to use our new Event component for the keynote talk. That's because the keynote has three speakers, and we only created space for a single speaker and image variable in the component.

We need to tweak the Event component so that it can handle an array (a list) of speakers and images.

<Event
  @title="Opening Keynote"
  @start="9:30am"
  @end="10:30am"
  @speakers={{array "Yehuda Katz" "Jen Weber" "Godfrey Chan"}}
  @images={{array "yehuda-katz" "jen-weber" "godfrey-chan"}}
/>

The {{array ...}} notation means that we're providing a list of items to the Event component instead of a single item.

In order to use that list in the Event component, we'll need to learn one more piece of syntax. The #each syntax allows us to loop over arrays.

<li class="event">
  <div class="time">
    <p>{{@start}}</p>
    <p>{{@end}}</p>
  </div>
  <h1>{{@title}}</h1>
  <h2>
    <ul>
-     <li>{{@speaker}}</li>
+     {{#each @speakers as |speaker|}}
+       <li>{{speaker}}</li>
+     {{/each}}
    </ul>
  </h2>
  <ul class="images">
-   <li>
-     <img src="https://emberconf.com/assets/images/people/{{@image}}.jpg">
-   </li>
+   {{#each @images as |image|}}
+     <li>
+       <img src="https://emberconf.com/assets/images/people/{{image}}.jpg">
+     </li>
+   {{/each}}
  </ul>
</li>

Let's break it down.

An #each diagram

Now that we've updated our component to allow us to provide speakers and images as arrays, let's update application.hbs so that all three of our talks use the component.

<ul class="events">
- <li class="event">
-   <div class="time">
-     <p>9:30am</p>
-     <p>10:30am</p>
-   </div>
-   <h1>Opening Keynote</h1>
-   <h2>
-     <ul>
-       <li>Yehuda Katz</li>
-       <li>Jen Weber</li>
-       <li>Godfrey Chan</li>
-     </ul>
-   </h2>
-   <ul class="images">
-     <li><img src="https://emberconf.com/assets/images/people/yehuda-katz.jpg"></li>
-     <li><img src="https://emberconf.com/assets/images/people/jen-weber.jpg"></li>
-     <li><img src="https://emberconf.com/assets/images/people/godfrey-chan.jpg"></li>
-   </ul>
- </li>
+ <Event
+   @title="Opening Keynote"
+   @start="9:30am"
+   @end="10:30am"
+   @speakers={{array "Yehuda Katz" "Jen Weber" "Godfrey Chan"}}
+   @images={{array "yehuda-katz" "jen-weber" "godfrey-chan"}}
+ />

  <Event
    @title="FastFlood: The Story of a Massive Memory Leak in FastBoot Land"
    @start="10:45am"
    @end="11:15am"
-   @speaker="Sergio Arbeo"
+   @speakers={{array "Sergio Arbeo"}}
-   @image="sergio-arbeo"
+   @images={{array "sergio-arbeo"}}

  />

  <Event
    @title="Octane: A Paradigm shift in EmberJS"
    @start="11:30am"
    @end="12:00pm"
-   @speaker="Suchita Doshi"
+   @speakers={{array "Suchita Doshi"}}
-   @image="suchita-doshi"
+   @images={{array "suchita-doshi"}}
  />

</ul>

And now that we've created our component, let's fill in a bunch more sessions!

<ul class="events">

  <Event
    @title="Opening Keynote"
    @start="9:30am"
    @end="10:30am"
    @speakers={{array "Yehuda Katz" "Jen Weber" "Godfrey Chan"}}
    @images={{array "yehuda-katz" "jen-weber" "godfrey-chan"}}
  />

  <Event
    @title="FastFlood: The Story of a Massive Memory Leak in FastBoot Land" 
    @start="10:45am"
    @end="11:15am"
    @speakers={{array "Sergio Arbeo"}}
    @images={{array "sergio-arbeo"}}
  />

  <Event
    @title="Octane: A Paradigm shift in EmberJS"
    @start="11:30am"
    @end="12:00pm"
    @speakers={{array "Suchita Doshi"}}
    @images={{array "suchita-doshi"}}
  />

+ <Event
+   @title="Break"
+   @start="12:00pm"
+   @end="1:30pm"
+ />
+
+ <Event
+   @title="Storytime: Georgia's Terrific Colorific Experiment"
+   @start="12:00pm"
+   @end="12:20pm"
+ />
+
+ <Event
+   @title="Welcome Back!"
+   @start="1:25pm"
+   @end="1:30pm"
+ />
+
+ <Event
+   @title="AST: the Secret Weapon to Transform a Codebase"
+   @start="1:30pm"
+   @end="2:00pm"
+   @speakers={{array "Sophia Wang"}}
+   @images={{array "sophia-wang"}}
+ />

</ul>

We can get away with leaving out the @speakers and @images, because #each doesn't do anything at all if it's iterating over nothing.

3. Cleaning Up the CSS

But after adding these events, we hit a little snag! Our CSS wasn't really designed for a situation with no speakers or images at all.

After adding more sessions, the page looks a little off.

Let's make two small tweaks to our CSS.

.event {
  display: grid;
  grid-template:
-    ".    .        images" auto
-    "time title    images" auto
+    ".    .        images" 1rem
+    "time title    images" fit-content(100%)
    "time speakers images" auto
-    ".    .        images" auto /
+    ".    .        images" 1rem /
    10rem 3fr 300px;
  padding: 0 1rem 0 3rem;
}

The short story is that we force the top and bottom placeholder row to a size of 1rem. After doing that, the title sometimes grows a little bit too much, and isn't always consistent.

To tell the title row to grow no larger than the size of its content, we can use fit-content(100%), which basically means: the height of this row is the size of the content, and it should never grow beyond 100% of that size. In contrast, auto allows the row to grow under certain conditions.

The second tweak is to add an additional color.

- .event:nth-child(3n + 1) {
+ .event:nth-child(4n + 1) {
  background-color: var(--c-pink);
}

- .event:nth-child(3n + 2) {
+ .event:nth-child(4n + 2) {
  background-color: var(--c-purple);
}

- .event:nth-child(3n + 3) {
+ .event:nth-child(4n + 3) {
  background-color: var(--c-blue);
}

+ .event:nth-child(4n + 4) {
+   background-color: var(--c-green);
+ }

After making these two tweaks, the schedule is looking great again!

And now, we're back in business.

In the next post, we'll talk about how to pull the data out into a separate file, so you don't need to edit the HTML just to add new talks to your schedule.