前面我們以原生Javascript手動完成SPA的基礎架構,從建立Component,到設定Route與Router,並搭配Webpack進行模組化的開發。前面實做主要希望讓各位了解SPA的實踐精神與原理,為了增強日後的實用性,接著試試來做些進階延伸的應用,讓你的SPA生態變得更豐富。
今天延伸應用的主題是「幫你的SPA套上Bootstrap」,Bootstrap是一個CSS Framework,由Twitter團隊開發,之後作為開源專案釋出。看看維基百科的說明:
Bootstrap是一組用於網站和網路應用程式開發的開源前端(所謂「前端」,指的是展現給終端使用者的介面。與之對應的「後端」是在伺服器上面執行的代碼)框架,包括HTML、CSS及JavaScript的框架,提供字體排印、表單、按鈕、導航及其他各種元件及Javascript擴充套件,旨在使動態網頁和Web應用的開發更加容易。
先看一下完成會是什麼樣子:
到Bootstrap官網參考安裝的步驟,首先我們透過NPM安裝Bootstrap:
$ npm install bootstrap
安裝完畢會在package.json的dependencies看到bootstrap與版本資訊,並且在node_modules裡多了bootstrap的資料夾。
之前我們有先安裝scss-loader,並搭配webpack將scss轉譯為css,這邊在src目錄裡建立一個scss的資料夾,專門放入相關scss檔,結構如下:
這邊說明一下各個scss檔:
都建立好後在進入點裡直接引入:
src/scss/style.scss:
//引入scss變數
@import 'variables';
// 從node_modules裡引入
@import '~bootstrap/scss/bootstrap.scss';
// 引入google font
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
//引入自訂義樣式
@import 'custom';
為了讓字型有變化,這邊我們多引入了google font的Roboto字型。引入後在variables與custom裡做以下設定:
src/scss/_custom.scss:
body {
font-family: 'Roboto', sans-serif;
}
src/scss/_variables.scss:
//改寫bootstrap變數設定
$primary: #00b1b1;
一切完成後,再次確認webpack.config.js裡有設定轉譯scss,以及是否將轉譯後的css做引入。
到Bootstrap官網裡有個Navbar的元件,把html代碼複製起來,我們在src裡建立components資料夾,專門放入共用組件:
src/components/Navbar.js:
export const Navbar = `
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
<a class="navbar-brand" href="#/">SPA with Router</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/post">Post</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu" aria-labelledby="dropdown">
<a class="dropdown-item" href="#">Profile</a>
<a class="dropdown-item" href="#">Logout</a>
</div>
</li>
</ul>
</div>
</nav>
`
這邊有兩種方式可以將Navbar整合至頁面裡:
1.在Home裡引入直接使用(較容易)
2.另外建立一個App.js做為最外層的外框容器組件,將Navbar.js引入這裡使用
第一個因為比較簡單,所以我們直接示範第二種,在src/pages裡建立App.js,並引入Navbar.js使用:
src/pages/App.js:
import { Navbar } from '../components/Navbar'
export const App = {
render: (conponent) => {
return `
${Navbar}
<div class="py-5">${conponent}</div>
`
},
}
這裡注意的是,pages裡組件輸出為物件裡含有render屬性的格式,其中會把html部份放入render裡。
這時多了App.js外框組件,並且Navbar.js在其中,那麼原先的Home.js要怎麼套入外框組件呢?其實只要把Home.js做點改變就好:
src/pages/Home.js:
import { App } from './App'
export const Home = {
render: () => {
const content = `
<div class="container">
<h1>Home page</h1>
<div>Welcome to my page!</div>
</div>
`
return App.render(content)
},
}
最後return把home的content內容套入App的畫面裡,所以返回App.render(content)
可以看到頁面開始切換了,不過你知道的,當你點了後面的Dropdown時,像極了Bug:
「什麼?竟然沒有出來選單O_o??」
這是因為Bootstrap4裡其實有搭配Jquery與popper.js,所以我們要下載上述套件,透過NPM安裝:
$ npm install jquery popper.js
然後在原本JS進入點index.js裡引入jquery與bootstrap自家搭配的JS就可以了:
src/index.js
//引入Jquery
import 'jquery'
import 'bootstrap/dist/js/bootstrap.bundle'
//引入scss
import './scss/style.scss'
//Router
import { Router } from './routes/Router'
//監聽hash變化&加載完畢事件
window.addEventListener('hashchange', Router)
window.addEventListener('load', Router)
今日完成了套入Bootstrap,幫網站添加了一些色彩樣式,明天會進入第二個進階的主題,怎麼在頁面渲染完成後產生作用,我們明天見!
參考資料:
Webpack 前端打包工具 - 客製化 Bootstrap 樣式並進行編譯