【單頁面博客從前端到後端】基於 DVA+ANTD 搭建博客先後臺界面

在上篇文章咱們已經搭建好了基礎的開發環境,接下來會介紹如何引入 DVA 和 ANTD ,以及在引入過程當中須要注意的問題。這裏只會詳細的書寫部分組件,其餘的組件都是大同小異。你能夠在 github倉庫 中找到這些組件。css

博客的原型圖

這裏我簡單的畫了一個博客的輪廓圖。這樣在寫組件的過程當中有助於有個總體性的思路,不迷路…前端

layout

添加目錄結構

blog 
├─ dist           # 輸出目錄
├─ task           # 這裏來放webpack處理和配置文件
├─ src
|  ├─ assets      # 靜態文件文件夾
|  ├─ components  # 組件
|  |  ├─ Home     # Home 頁面的文件夾
|  |  ├─ Archive 
|  |  ├─ About
|  |  ├─ Admin    # 後臺界面文件夾
|  |  ├─ Header.js    # 公共的 Header 組件
|  |  ├─ Footer.js    # 公共的 Footer 組件
|  |  ├─ UserCard.js  # 公共的 UserCard 組件
|  |  ├─ Login.js     # 公共的 Login 組件
|  ├─ containers  # Redux 的容器組件
|  |  ├─ Home.js      # Home 組件的容器
|  |  ├─ Archive.js
|  |  ├─ About.js
|  |  ├─ Admin        # 後臺各界面的容器文件夾
|  ├─ router.js   # React 路由
|  └ index.js     # 入口文件
| package.json

引入 DVA 和 ANTD

DVA 的簡單引入

Lightweight front-end framework based on redux, redux-saga and react-router@2.x. (Inspired by elm and choo)node

要知道 dva 是對 redux , redux-saga , react-router 的封裝,使用上有點像 express.js ,那麼你就要多少對他們有所瞭解,dvagithub 倉庫 有詳細的入門指南、概念和示例,能夠先去了解一下 。react

更改入口文件 src/index.jswebpack

import dva from 'dva'
const app = dva()

app.router(require('./router'))
app.start('#root')

新建路由文件 src/router.jsgit

import React from 'react'
import { Router, Route, IndexRoute, IndexRedirect } from 'dva/router'

import AppLayout from './container/App'
import Home from './container/Home'
import Archive from './container/Archive'
import About from './container/About'
import Article from './container/Article'
import AdminArticles from './container/Admin/Articles'
import AdminKeywrods from './container/Admin/Keywords'
import AdminEditor from './container/Admin/Editor'
import AdminLayout from './container/Admin/Admin'

export default ({history, app}) => {
    return (
        <Router history={history}>
            <Route path="/" component={AppLayout}>
                <IndexRoute component={Home} />
                <Route path="archive" component={Archive} />
                <Route path="about" component={About} />
                <Route path="article/:id" component={Article} />
                <Route path="admin" component={AdminLayout}>
                    <IndexRedirect to="articles" />
                    <Route path="articles" component={AdminArticles} />
                    <Route path="keywords" component={AdminKeywrods} />
                    <Route path="editor" component={AdminEditor} />
                </Route>
            </Route>
        </Router>
    )
}

從這裏能夠看出, dva 本身在內部引入 react-router-redux ,而後使用 react-router-redux 提供的 combineReducers routerRedux 合併到用戶的 reducersgithub

限於文章的篇幅,dvamodel 的設計會放到下一次的文章來描述web

引入 ANTD

按需加載express

在引入 ANTD 以前,咱們先來實現 按需加載 。其實概念很簡單,就是咱們在引入一個樣式庫的時候,每每只會用到這個樣式庫的部分組件,可是工具會把整個組件庫都打包到咱們的項目中,這是咱們不想看到的。按需加載 就是用來打包咱們引入的組件,可使用 babel-plugin-import 來具體實現。json

task/config.jsbabel-loader 的 plugins 配置中添加:
["import", { "libraryName": "antd", "style": true }]

自定義主題

由腳手架 atool-build官網介紹,咱們已經本身配置並新建好了主題文件 theme.js

添加 less-loader 處理樣式文件

上節咱們只是添加了對 .module.less 文件進行編譯,在自定義主題時,須要對 less 變量進行覆蓋,因此要求 babel-plugin-importstyle 選項設置爲 true ,讓它導出 antd 組件的 .less 樣式文件才能進行變量覆蓋操做。

task/config.jsmodule.rules 追加

{
    test: function(path){
        return /\.less$/.test(path) && !/\.module\.less$/.test(path)
    },
    loader: ExtractTextPlugin.extract({
        fallback: 'style-loader', 
        use: [
            {
                loader: 'css-loader', 
            },
            {
                loader: 'postcss-loader',
                options: {
                    plugins: postcssPlugins
                }
            },
            {
                loader: 'less-loader', 
                options: {"modifyVars": theme}
            }
        ]
    })
},

注意 /\.less/ 至少會匹配到 .module.less.less 文件,因此要排除 .module.less ,由於它須要被 css-module 處理。

你也可能會經過添加 exclude , include 來對樣式庫中的 less 文件和本身編寫的文件進行區別,畢竟樣式庫確定都是從 node_modules 目錄中加載,而本身的是從 src 目錄下加載的。也正由於樣式庫是從 node_modules 目錄下加載的,因此這樣作可能會致使下降 webpack 的編譯速度。

添加容器組件和展現組件

容器組件

/src/containers 下新建 App.js

import React, { PropTypes } from 'react'
import { connect } from 'dva'
import { Layout, Menu, Breadcrumb, Row, Col, Icon } from 'antd'
import HeaderComponent from 'components/Header'
import FooterComponent from 'components/Footer'
import LoginModel from 'components/Login'
const { Header, Content, Footer } = Layout

const App = ({children, routes}) => {
    return (
        <Layout>
            <Header>
                <HeaderComponent routes={routes}>
                    <LoginModel doLogin={() => {}} />
                </HeaderComponent>
            </Header>
            <Content style={{ margin: '24px 100px 0', background: '#fff', minHeight: 280, overflow: 'hidden' }}>
                {children}
            </Content>
            <Footer>
                <FooterComponent />
            </Footer>
        </Layout>
    )
}

export default connect()(App)

由於 dva 封裝了 redux源文件 中也是直接導出 react-reduxconnect 方法。因此在建立容器組件的時候仍是等同於 react-redux

注意,這個 App組件是做爲子路由組件的父組件,即 children 表明的就是那些子組件 Home , Archive

其餘的展現組件,即 /src/containers 文件夾下面的組件,都是大同小異,就不一一贅述。

展現組件

咱們看到 src/container/App.js 展現組件,引入了一個 HeaderComponent ,在 src/components 下面新建一個 Header.js

import React from 'react'
import { Layout, Menu, Breadcrumb, Row, Col } from 'antd'
import { Router, Link } from 'dva/router'

const HeaderComponent = (props) => {
    const { children, routes } = props
    const routePath = (routes[routes.length - 1] || {}).path || '/'
    return (
        <div>
            <Row>
                <Col span={16}>
                    <Menu
                        mode="horizontal"
                        defaultSelectedKeys={[routePath]}
                        style={{ lineHeight: '64px', backgroundColor: 'transparent' }}
                    >
                        <Menu.Item key="/"><Link to="/">Home</Link></Menu.Item>
                        <Menu.Item key="archive"><Link to="archive">Archive</Link></Menu.Item>
                        <Menu.Item key="about"><Link to="about">About me</Link></Menu.Item>
                    </Menu>
                </Col>
                <Col span={8}>
                    <div style={{ lineHeight: '64px', float: 'right', padding: '0 20px' }}>
                        {children}
                    </div>
                </Col>
            </Row>
        </div>
    )
}

export default HeaderComponent

這就是個普通的 React 的展現組件沒什麼好說的,這些組件能夠直接在 Antd 的官網上找到用法,並且都有示例代碼。

const routePath = (routes[routes.length - 1] || {}).path || '/'
找到路由路徑中的最後一個名稱,如 /home 中的 home ,做爲 Menu 的默認選中項,這樣在當前頁面刷新,就可讓當前頁面對應的導航高亮。

其餘的展現型組件也都是大同小異,你能夠在 github倉庫 中找到它們的實現。

引入 url-loader 來處理文件路徑

task/config.js 中的 module.rules 追加:

{
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
    options: {
        limit: 10000,
        name: 'img/[name].[hash:7].[ext]'
    }
},
{
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    options: {
        limit: 10000,
        name: 'fonts/[name].[hash:7].[ext]'
    }
},

關於 url-loader 的配置方法,能夠在 webpack 的文檔中查看

小結

這篇文章主要是引入了兩個重要的庫 dvaantd ,以及編寫部分展現組件。接下來,咱們會對 dva 的數據層,已經後臺初步搭建,同步進行先後端的開發。

相關文章
相關標籤/搜索