基本功練習: Hacker News! — Part 4: Recursion
基本功練習: 使用純 JS + Redux 把 Hacker News 做出來。
前情提要
我們個別頁面已經寫好啦,現在該來處理醜醜的留言顯示了!
留言顯示
開始前,我們先來觀察一下 comments。
注意到了嗎?他是一層又一層的!(nested object)
我們在寫 comments 這頁時,要把這個特點考慮進去。
先繼續依照 React 的 Component 邏輯,把每個 comments 拆到他們各自的 Component 裡面吧:
item.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 以上省略
export default async function Item() {
const story = await getStory();
const hasComments = story.comments.length > 0;
view.innerHTML = `
<div>
${Story(story)}
</div>
<hr/>
${hasComments ? story.comments.map(comment => Comment(comment)).join('') : '沒留言耶'}
`
}
// 以下省略
Comment.js:
1
2
3
4
5
6
7
8
9
10
11
export default function Comment(comment) {
console.log(comment);
return `
<div class="nested-comments-0">
<p class="comment-header">
${comment.user} | ${comment.time_ago}
</p>
${comment.content}
</div>
`
}
我們來看看畫面:
留言出來了沒錯,可是有看到每一筆下面還有一層 comments 嗎?
這就是我們之前觀察到的 nested comments,我們需要處理他!
我們需要讓 Comment 一直產生畫面直到 comments 裡面沒有任何 comments 為止。
所以,先寫個判斷是否有 nested comments 吧。
1
const hasNestedComments = comment.comments.length > 0;
如果有 nested comments 的話,那我們加個判斷讓他產生畫面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default function Comment(comment) {
const hasNestedComments = comment.comments.length > 0;
return `
<div class="nested-comments-0">
<p class="comment-header">
${comment.user} | ${comment.time_ago}
</p>
${comment.content}
${hasNestedComments ? comment.comments.map(comment => Comment(comment)).join("") : ""}
</div>
`
}
1
${hasNestedComments ? comment.comments.map(comment => Comment(comment)).join("") : ""}
這一行的意思是,如果 hasNestedComments = true 的話,那 Comment function 會一直自己呼叫自己直到 hasNestedComments = false。
也就是所謂的 recursion function!
再修改一下 css,讓每一層巢狀 comments 都會被往右邊推。
1
<div class="nested-comments-${comment.level}">
我們的留言區就變成這樣了~
快寫完了!現在我們只剩下最後一個功能,我的最愛頁面。
而這一塊,我想用 Redux pattern。
這樣就可以讓用戶在新聞列表直接將喜歡的新聞加進我的最愛頁面,也可以在將新聞從我的最愛移除。
最重要的是,在我們切換頁面時,資料不會流失!