React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

code_mcx發表於2017-12-18

上一節使用create-react-app腳手架搭建了基本專案骨架,這一節繼續製作專案需要的字型圖示和頁面主路由的搭建

字型圖示製作

為什麼要使用字型圖示?

  1. 圖示放大或縮小不會被拉伸,會保持足夠的清晰度
  2. 顏色可以隨意設定。如果使用普通圖片,圖片顏色已經是設計好的,如果要換顏色需要藉助工具來對圖片進行修改

製作字型圖片首先我們需要svg圖片。svg圖片可以從iconfont阿里向量圖示庫自行選擇。筆者已經下載了專案需要的svg圖片

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

藉助一個叫iconmoon的網站。瀏覽器地址上輸入:icomoon.io/app

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

點選上方的Import Icons按鈕彈出選擇對話方塊,選擇剛剛下載的svg圖片

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

點選開啟

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

然後選中所有的圖示,點選Generate Font

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

跳轉到如下介面,點選download

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建
下載後面的壓縮包如下

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

該壓縮包包含了字型圖片使用的demo,和生成的字型圖示檔案及相關樣式。在專案src目錄下面新建一個assets目錄然後再新建一個stylus目錄用來放置styl檔案,解壓壓縮包把裡面的style.cssfonts資料夾複製出來放置到stylus目錄下。

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

對fonts目錄下的檔案和style.css稍做修改

將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"

複製程式碼

修改後的檔案結構如下

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

頁面路由搭建

準備

先對專案結構做一些修改

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

刪除App.test.jslogo.svg。在src目錄下面新建一個components目錄,將App.jsApp.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檔案,將htmlbodydiv#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

複製程式碼

修改後的目錄結構如下

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

搭建路由

我們先來看一下頁面結構

推薦頁

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

排行榜

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

搜尋

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

這三個頁面是一個Tab選項卡模式頂部是Logo,三個Tab按鈕中間是Tab對應的檢視,Logo和Tab按鈕是不變的,所以這裡中間就設計成一個路由的檢視介面,三個Tab對應三個路由

編寫Logo及Tab樣式 在assets目錄下面新建一個imgs資料夾用來存放圖片,這裡放了三張圖片,其中一張就是頭部Logo圖片,其它兩張後面會用到

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

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目錄下面新建recommendrankingsearch三個目錄用來存放推薦、排行、搜尋頁面相關元件

React全家桶構建一款Web音樂App實戰(二):字型圖示製作及頁面路由搭建

在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分支

相關文章