基本功練習: Hacker News! — Part 1: 骨架
基本功練習: 使用純 JS + Redux 把 Hacker News 做出來。
Hacker News!
這是簡單版的 Hacker News 成品~
最近在練習 JS 基本功,不用框架直接用了 vanilla JS + Redux 把它寫出來。
之後會同場加映 React 版本(包含 Hooks)。
我們開始吧~
骨架
其實 Hacker News 網頁的本身框架很簡單,就是 header 加一個 nav 再來一個 body container,這邊就不多講 HTML,直接跳 JS 的部分。
因為練習基本功所以不用框架,但我還是想按照類似結構:使用單個 html 檔案,並將其他網頁語法用 JS 填進去。
如果我想要這個 app 的框架原理跟 React 類似,那我們回想下 React 的基礎結構:
React 的 setup 原理採用只有單個 html 檔案,並將其他網頁語法用 JS 填進去。
1
2
3
4
5
6
7
<div id="root"></div>
ReactDOM.render(<App />, document.getElementbyId('root'));
class App extends React.Component {
//...
}
Ok,那我們以此類推,用 JS module 把整個畫面寫出來,然後想辦法讓 JS 只 update 一個地方即可。
關於 routing 的部分,我們用 hash router 來連結不同頁面,為了節省時間用第三方插件 Navigo。(用純 JS 把 Router 寫出來太費時了,我還要寫 React 啊!)
我們先寫一些測試 code 確保這個寫法是 OK 的。
首先是單個 html 框架:
1
2
3
4
5
6
7
8
9
10
<!-- 上面省略 -->
<div id="route-container">
<div id="router-outlet"></div>
</div>
<script type="module" src="app.js"></script>
<script src="//unpkg.com/navigo@6"></script>
<!-- 下面省略 -->
先把我們的 Router 架好,並在 app.js 設定它:
App.js:
1
2
3
4
5
6
7
8
9
import RouterHandler from './router.js'
class App {
constructor() {
new RouterHandler();
}
}
new App();
Router 本身:
router.js:
1
const router = new Navigo(null, true, '#');
有了 router,就可以切換頁面了。
跟著 React 的結構繼續走,畫面要更新那 JS 會直接在某個 div 裡面添加資訊,這裡是:
1
<div id="router-outlet"></div>
所以我們需要一個 querySelector,就叫他 view.js。
view.js:
1
export default document.querySelector('#router-outlet');
然後把我們要的資訊裝進去。
stories.js:
1
2
3
4
5
import view from '../utils/view.js';
export default function Stories(path) {
view.innerHTML = `<div>${path}</div>`;
}
我把每個 route 的放進一個叫 Stories 的 container 頁面(因為 Stories 裡面之後會裝一條條單個 Story)。
為什麼會是 path 當 parameter 咧?
之前提到過,我們用 hash router 來連結不同頁面,而用戶點擊不同頁面的時候,我的 router 會顯示不同畫面。
每個畫面產生的東西(之後會從 API 抓資訊),當然是透過 path 進去。
我們看下 Navigo 的 doc,把 router 切換寫好。
router.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
import Stories from './pages/stories.js';
const router = new Navigo(null, true, '#');
export default class RouterHandler {
constructor() {
this.createRoutes()
}
createRoutes() {
const routes = [
{ path: '/', page: Stories },
{ path: '/new', page: Stories },
{ path: '/ask', page: Stories },
{ path: '/show', page: Stories }
];
routes.forEach(({ path, page }) => {
router.on(path, () => {
page(path);
}).resolve();
})
}
}
頁面 setup 就完成了,我們下一集會接著把每條新聞用 API 抓進來。