上一節使用create-react-app腳手架搭建了基本項目骨架,這一節繼續製做項目須要的字體圖標和頁面主路由的搭建css
爲何要使用字體圖標?html
製做字體圖片首先咱們須要svg圖片。svg圖片能夠從iconfont阿里矢量圖標庫自行選擇。筆者已經下載了項目須要的svg圖片react
藉助一個叫iconmoon的網站。瀏覽器地址上輸入:icomoon.io/appgit
點擊上方的Import Icons按鈕彈出選擇對話框,選擇剛剛下載的svg圖片github
點擊打開web
而後選中全部的圖標,點擊Generate Fontcanvas
跳轉到以下界面,點擊download瀏覽器
該壓縮包包含了字體圖片使用的demo,和生成的字體圖標文件及相關樣式。在項目src目錄下面新建一個assets目錄而後再新建一個stylus目錄用來放置styl文件,解壓壓縮包把裏面的style.css和fonts文件夾複製出來放置到stylus目錄下。ruby
對fonts目錄下的文件和style.css稍作修改bash
將fonts下面的文件名都重命名爲icomusic,將style.css重命名爲font.styl。而後打開icomusic將裏面的花括號和分號去掉變成標準的styl語法格式,把裏面的iconmoon所有替換爲icomusic
font.styl
@font-face
font-family: 'icomusic'
src: url('fonts/icomusic.eot?nnepb1')
src: url('fonts/icomusic.eot?nnepb1#iefix') format('embedded-opentype'),
url('fonts/icomusic.ttf?nnepb1') format('truetype'),
url('fonts/icomusic.woff?nnepb1') format('woff'),
url('fonts/icomusic.svg?nnepb1#icomusic') format('svg')
font-weight: normal
font-style: normal
[class^="icon-"], [class*=" icon-"]
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomusic' !important
speak: none
font-style: normal
font-weight: normal
font-variant: normal
text-transform: none
line-height: 1
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
.icon-back:before
content: "\e900"
.icon-delete:before
content: "\e901"
.icon-fe-music:before
content: "\e902"
.icon-list-play:before
content: "\e903"
.icon-music:before
content: "\e904"
.icon-next:before
content: "\e905"
.icon-pause:before
content: "\e906"
.icon-play:before
content: "\e907"
.icon-play-list:before
content: "\e908"
.icon-previous:before
content: "\e909"
.icon-search:before
content: "\e90a"
.icon-shuffle-play:before
content: "\e90b"
.icon-single-play:before
content: "\e90c"
.icon-user:before
content: "\e90d"
複製代碼
修改後的文件結構以下
先對項目結構作一些修改
刪除App.test.js、logo.svg。在src目錄下面新建一個components目錄,將App.js和App.styl放置在components目錄下面,將App.styl中的內容所有刪除,而後刪除App.js中render函數中的div標籤下面的內容
App.js
//import React, { Component } from 'react';
import React from 'react';
//import logo from './logo.svg'; 刪除此行
import './App.styl';
class App extends React.Component {
render() {
return (
//<div className="App">
<div className="app">
//<header className="App-header">
// <img src={logo} className="App-logo" alt="logo" />
// <h1 className="App-title">Welcome to React</h1>
//</header>
//<p className="App-intro">
// To get started, edit <code>src/App.js</code> and save to reload.
//</p>
</div>
);
}
}
export default App;
複製代碼
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
//import App from './App';
import App from './components/App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
複製代碼
修改index.css文件,將html、body、div#root寬高都設置爲100%,在body上設置根字體和字體大小
index.css
html, body, #root {
width: 100%;
height: 100%;
}
body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
}
::-webkit-scrollbar {
width: 0;
height: 0;
}
複製代碼
最後在stylus目錄下新增reset.styl文件
reset.styl
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video
margin: 0
padding: 0
border: 0
vertical-align: baseline
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section
display: block
body
line-height: 1
ol, ul
list-style: none
blockquote, q
quotes: none
blockquote:before, blockquote:after,
q:before, q:after
content: ''
content: none
table
border-collapse: collapse
border-spacing: 0
複製代碼
修改後的目錄結構以下
咱們先來看一下頁面結構
推薦頁
排行榜
搜索
這三個頁面是一個Tab選項卡模式頂部是Logo,三個Tab按鈕中間是Tab對應的視圖,Logo和Tab按鈕是不變的,因此這裏中間就設計成一個路由的視圖界面,三個Tab對應三個路由
編寫Logo及Tab樣式 在assets目錄下面新建一個imgs文件夾用來存放圖片,這裏放了三張圖片,其中一張就是頭部Logo圖片,其它兩張後面會用到
App.js
import React from 'react';
import logo from "../assets/imgs/logo.png"
import '../assets/stylus/reset.styl'
import './App.styl';
class App extends React.Component {
render() {
return (
<div className="app">
<header className="app-header">
<img src={logo} className="app-logo" alt="logo" />
<h1 className="app-title">Mango Music</h1>
</header>
<div className="music-tab">
<div className="tab-item selected">
<span>推薦</span>
</div>
<div className="tab-item">
<span>排行榜</span>
</div>
<div className="tab-item">
<span>搜索</span>
</div>
</div>
</div>
);
}
}
export default App;
複製代碼
App.styl
.app
width: 100%
height: 100%
color: #DDDDDD
background-color: #212121
.app-header
height: 55px
line-height: 55px
color: #FFD700
text-align: center
.app-logo
width: 30px
height: 25px
margin-top: -5px
vertical-align: middle
.app-title
display: inline-block
height: 55px
margin-left: 10px
font-size: 18px
font-weight: 300
.music-tab
display: flex
height: 30px
line-height: 30px
color: #DDDDDD
text-align: center
.tab-item
flex: 1
複製代碼
三個Tab採用flex佈局,自適應屏幕寬度
編寫推薦頁、排行旁頁、搜索頁三個組件。在components目錄下面新建recommend、ranking和search三個目錄用來存放推薦、排行、搜索頁面相關組件
在recommend目錄下建立Recommend.js和recommend.styl。React約定組件的名字首字母大寫。對應的js文件名和組件同樣大寫(不強制),組件對應一個樣式文件,命名和組件名同樣方便尋找
Recommend.js
import React from "react"
import "./recommend.styl"
class Recommend extends React.Component {
render() {
return (
<div className="music-recommend">
Recommend
</div>
);
}
}
export default Recommend
複製代碼
recommend.styl內容暫時爲空
一樣在ranking目錄和search目錄下新建Ranking.js、ranking.styl和Search.js、search.styl
Ranking.js
import React from "react"
import "./ranking.styl"
class Ranking extends React.Component {
render() {
return (
<div className="music-ranking">
Ranking
</div>
);
}
}
export default Ranking
複製代碼
Search.js
import React from "react"
import "./search.styl"
class Search extends React.Component {
render() {
return (
<div className="music-search">
Search
</div>
);
}
}
export default Search
複製代碼
編寫路由
回到App.js中,import路由相關組件
import {BrowserRouter as Router, Route, Switch, Redirect, NavLink} from "react-router-dom"
複製代碼
在App組件中導入Recommend、Ranking和Search組件,App的根使用Router包裹,加入一個div包裹Route組件
import Recommend from "./recommend/Recommend"
import Ranking from "./ranking/Ranking"
import Search from "./search/Search"
複製代碼
<div className="music-view">
{/*
Switch組件用來選擇最近的一個路由,不然最後一個沒有指定path的路由也會顯示
Redirect重定向到列表頁
*/}
<Switch>
<Route path="/recommend" component={Recommend} />
<Route path="/ranking" component={Ranking} />
<Route path="/search" component={Search} />
<Redirect from="/" to="/recommend" />
<Route component={Recommend} />
</Switch>
</div>
複製代碼
在app.styl中增長如下樣式填充屏幕剩餘高度
.music-view
position: fixed
top: 88px
left: 0
bottom: 52px
width: 100%
複製代碼
使用NavLink組件包裹Tab,使其具備路由跳轉功能
<div className="tab-item">
<NavLink to="/recommend" className="nav-link">
<span>推薦</span>
</NavLink>
</div>
<div className="tab-item">
<NavLink to="/ranking" className="nav-link">
<span>排行榜</span>
</NavLink>
</div>
<div className="tab-item">
<NavLink to="/search" className="nav-link">
<span>搜索</span>
</NavLink>
</div>
複製代碼
設置NavLink組件樣式
.nav-link, .link
display: block
color: inherit
text-decoration: none
&.active
color: #FFD700
border-bottom: 2px solid #FFD700
複製代碼
NavList組件最後渲染的是一個a標籤,使用以上樣式對其進行美化,在當前NavLink組件被激活的時候會自動添加上active樣式
App.js和app.styl完整代碼以下
App.js
import React from 'react';
import {BrowserRouter as Router, Route, Switch, Redirect, NavLink} from "react-router-dom"
import Recommend from "./recommend/Recommend"
import Ranking from "./ranking/Ranking"
import Search from "./search/Search"
import logo from "../assets/imgs/logo.png"
import '../assets/stylus/reset.styl'
import './App.styl';
class App extends React.Component {
render() {
return (
<Router>
<div className="app">
<header className="app-header">
<img src={logo} className="app-logo" alt="logo" />
<h1 className="app-title">Mango Music</h1>
</header>
<div className="music-tab">
<div className="tab-item">
<NavLink to="/recommend" className="nav-link">
<span>推薦</span>
</NavLink>
</div>
<div className="tab-item">
<NavLink to="/ranking" className="nav-link">
<span>排行榜</span>
</NavLink>
</div>
<div className="tab-item">
<NavLink to="/search" className="nav-link">
<span>搜索</span>
</NavLink>
</div>
</div>
<div className="music-view">
{/*
Switch組件用來選擇最近的一個路由,不然最後一個沒有指定path的路由也會顯示
Redirect重定向到列表頁
*/}
<Switch>
<Route path="/recommend" component={Recommend} />
<Route path="/ranking" component={Ranking} />
<Route path="/search" component={Search} />
<Redirect from="/" to="/recommend" />
<Route component={Recommend} />
</Switch>
</div>
</div>
</Router>
);
}
}
export default App;
複製代碼
app.styl
.app
width: 100%
height: 100%
color: #DDDDDD
background-color: #212121
.app-header
height: 55px
line-height: 55px
color: #FFD700
text-align: center
.app-logo
width: 30px
height: 25px
margin-top: -5px
vertical-align: middle
.app-title
display: inline-block
height: 55px
margin-left: 10px
font-size: 18px
font-weight: 300
.music-tab
display: flex
height: 30px
line-height: 30px
color: #DDDDDD
text-align: center
.tab-item
flex: 1
.music-view
position: fixed
top: 88px
left: 0
bottom: 52px
width: 100%
.nav-link, .link
display: block
color: inherit
text-decoration: none
&.active
color: #FFD700
border-bottom: 2px solid #FFD700
複製代碼
在本章節講解了如何製做字體圖標,根據頁面設計基本路由結構
後續更新中...
完整項目地址:github.com/code-mcx/ma…
本章節代碼在chapter2分支