基本功練習: Hacker News! — Part 7: 「我的最愛」
基本功練習: 使用純 JS + Redux 把 Hacker News 做出來。
前情提要
最後衝刺了,我們把 「我的最愛」寫出來吧!
我的最愛: 頁面
既然要這個頁面,那我們就必須弄一個新的,然後把他加進 routes 裡面:
router.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 省略以上
import Favorites from './pages/favorites.js';
createRoutes() {
const routes = [
{ path: '/', page: Stories },
{ path: '/new', page: Stories },
{ path: '/ask', page: Stories },
{ path: '/show', page: Stories },
{ path: '/item', page: Item },
{ path: '/favorites', page: Favorites }
];
// 省略以下
favorites.js:
1
2
3
4
5
import view from '../utils/view.js';
export default function Favorites() {
view.innerHTML = `<div>Favorites</div>`
}
還是一樣,先讓它出來,我們再來改內容。
所以「我的最愛」要幹嘛,顯示 favorite state 啊,廢話。
把 store 丟進來吧!
1
2
3
4
import store from '../store.js';
const { favorites } = store.getState();
const hasFavorites = favorites.length > 0;
我們直接取得 favorites 的 state,接著像其他頁面一樣寫判斷,如果有的資料話才顯示,沒有的話顯示訊息叫用戶加吧~
favorites.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import view from '../utils/view.js';
import checkFavorite from '../utils/checkFavorite.js';
import store from '../store.js';
import Story from '../components/Story.js';
export default function Favorites() {
const { favorites } = store.getState();
const hasFavorites = favorites.length > 0;
view.innerHTML = `<div>
${hasFavorites ? favorites.map(story => Story({
...story,
isFavorite: checkFavorite(favorites, story)
})).join('') : "加一點東西進來吧!"}
</div>`
}
耶,可以加進去了!
但怎麼刪不掉咧?因為你還沒寫啊 XD
刪除的邏輯跟 Stories 很類似,複製貼上改一改就好了,像這樣…
1
2
3
4
5
6
7
8
document.querySelectorAll('.favorite').forEach(favoriteButton => {
favoriteButton.addEventListener('click', function() {
const story = JSON.parse(this.dataset.story);
const isFavorited = checkFavorite(favorites, story);
store.dispatch({ type: isFavorited ? "REMOVE_FAVORITE" : "ADD_FAVORITE", payload: { favorite: story } })
Favorites();
});
});
不過為什麼 addEventListener 的 callback function 不是 async 了?
因為 Favorites 沒有用到 API,所以就不需要用到 async function 啊。
記得發完 action 後,讓 Favorite 重刷即可。
最後…
favorites.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import view from '../utils/view.js';
import checkFavorite from '../utils/checkFavorite.js';
import store from '../store.js';
import Story from '../components/Story.js';
export default function Favorites() {
const { favorites } = store.getState();
const hasFavorites = favorites.length > 0;
view.innerHTML = `<div>
${hasFavorites ? favorites.map(story => Story({
...story,
isFavorite: checkFavorite(favorites, story)
})).join('') : "Add some favorites!"}
</div>`
document.querySelectorAll('.favorite').forEach(favoriteButton => {
favoriteButton.addEventListener('click', function() {
const story = JSON.parse(this.dataset.story);
const isFavorited = checkFavorite(favorites, story);
store.dispatch({ type: isFavorited ? "REMOVE_FAVORITE" : "ADD_FAVORITE", payload: { favorite: story } })
Favorites();
});
});
}
我們的簡易版 Hacker News 就寫好了!
耶~~