React + Antd 實現後臺管理系統

React 介紹

  • Facebook 開源的一個 JavaScript 庫
  • React 結合生態庫構成一個 MV* 框架
  • React 特色:
    • 聲明式編碼 (只須要聲明在哪裏作什麼,而無需關心如何實現,好比數組原型上的那些高階函數。編程式實現:須要以具體代碼表達在哪裏作什麼,如何實現,好比 for 循環之類的。)
    • Component-Based (組件化編碼)
    • 高效 (高效的 DOM Diff 算法,最小化頁面重繪)
    • 單向數據流
  • 生態介紹
    • React-Router (Vue-Router)
    • Redux (Vuex)
    • Axios
    • Babel
    • Webpack

React 生命週期

  • getDefaultProps
  • getInitialState
  • componentWillMount
  • render (必須)
  • componentDidMount
  • componentWillReceiveProps
  • shouldComponentUpdate (<--- this.setState())
  • componentWillUpdate (<--- this.forceUpdate())
  • componentDidUpdate
  • componentWillUnmount
import React, { Component } from 'react';

class Child extends Component {
	// 如下生命週期按順序執行
	// 首次會執行 componentWillMount、render、componentDidMount
	// mount 鉤子只會在組件中調用一次,其餘的調用屢次

	componentWillReceiveProps(newProps) {
		console.log('will use newProps', newProps);
	}

	shouldComponentUpdate(newProps) {
		// 接受新的 props,若是返回 false, 就不會再調用 render 生命週期了

		console.log('should update', newProps);
		return newProps.value === 3 ? false : true;
	}

	componentWillUpdate(newProps) {
		console.log('will update', newProps);
	}

	componentWillMount() {
		console.log('will mount');
	}

	render() {
		console.log('render');
		return (
			<div>Child</div>
		);
	}

	componentDidMount() {
		console.log('did mount');
	}

	componentDidUpdate(oldProps) {
		// 接收老的 props
		// 好比父組件設置了 state 裏面的值,這裏的 oldProps 裏面的值就是 state 以前的值

		console.log('did update', oldProps);
	}
}

export default Child;
複製代碼

項目依賴安裝

  • axios
  • antd (使用的 less,能夠修改屬於本身的主題,之因此咱們能夠引入 antd.css,是由於 less 文件已經被編譯打包了,可是 antd 實際上是採用 less 的方式來編寫樣式的!)
  • react-router-dom
  • redux
  • less (安裝less)
  • less-loader (須要暴露出 webpack 配置: yarn eject)
  • babel-plugin-import (按需加載組件代碼和樣式,好比咱們引入了一個 Button 組件,那麼相應的也只會引入 Button 的樣式文件)

配置 lesscss

// 暴露出 webpack 配置,編輯 webpack.config.js
// 編輯完以後重啓服務便可
// 記住:use 採用從後到前來進行解析,loader 不要寫反了

{
  test: /\.less$/,
  use: [
    require.resolve('style-loader'),
    {
      loader: require.resolve('css-loader'),
      options: {
        importLoaders: 1
      }
    }, {
      loader: require.resolve('postcss-loader'),
      options: {
        ident: 'postcss',
        plugins: () => [
          require.resolve('postcss-flexbugs-fixes')
        ]
      }
    }, {
      loader: require.resolve('less-loader')
    }
  ]
},
複製代碼

配置按需加載 (安裝 babel-plugin-import)react

// 打開 webpack.config.js 文件

{
  test: /\.(js|mjs|jsx|ts|tsx)$/,
  include: paths.appSrc,
  loader: require.resolve('babel-loader'),
  options: {
    customize: require.resolve(
      'babel-preset-react-app/webpack-overrides'
    ),
    // 添加以下配置便可
    // 項目打包就只會打包你引入了的組件和樣式
    plugins: [
      ['import', {
        libraryName: "antd",
        // 若是指定是 "css", 那麼它就會引入 "antd/lib/button/style/css"
        // 不過,你修改按鈕的主題色的時候,就沒法修改了,由於咱們修改主題是經過改變 less 變量
        // 而 css 文件是已經編譯打包好了的
        // style: "css"
        
        // 指定爲 true,它就會加載 "antd/lib/button/style"下的 less 模塊
        // 並將全部 less 模塊進行動態編譯成 css 文件
        style: true, 
      }]
  },
},
複製代碼

修改 Antd 的主題色webpack

{
  loader: require.resolve('less-loader'),
  options: {
    modules: false,
    modifyVars: {
      // 修改 antd 的主題色
      "@primary-color": "#f9c700"
    }
  }
}
複製代碼

項目路由配置

  • 項目的首頁與登陸頁是同一層級的路由,因此配置的時候須要提早想好
  • 定義一個 router.js 文件,放置第一層級路由
  • 經過 this.props.children 獲取組件內部的路由配置
// router.js

<Router>
    <Route path='/login' component={Login} />
    <Route path='/admin' render={(props) =>
        <Admin>
            <Route path={`${props.match.path}/home`} component={Home} />
            <Route path={`${props.match.path}/ui/buttons`} component={Buttons} />
        </Admin>
    } />
</Router>

// Admin.js (用來對Home頁面的一個佈局)

class Admin extends Component {
    render() {
        return (
            <Row className="container">
                <Col span={4} className="nav-left">
	                <NavLeft />
                </Col>
                <Col span={20} className="main">
                    <Header />
                    <Row className="content">
                        // 渲染 Admin 組件內部的 Route
                    	{this.props.children}
                    </Row>
                    <Footer />
                </Col>
            </Row>
        );
    }
}
複製代碼

Mock 數據以及接口請求封裝

  • easy mock (編寫在線的接口)
  • mock (配置須要接口返回的數據)
  • axios (請求接口)
// 封裝接口請求
import axios from 'axios';
import { Modal } from 'antd';

const baseURL = 'https://....';

class Axios {
    static ajax(options) {
        return new Promise((resolve. reject) => {
            axios({
                method: 'get',
                url: options.url,
                baseURL: baseURL,
                timeout: 5000,
                params: (options.data && options.data.params) || ''
            }).then((response) => {
                if (response.status === '200') {
                    const res = response.data;
                    if (res.code === 0) {
                        resolve(res);
                    } else {
                        // 接口數據報錯
                        Modal.info({
                            title: '提示',
                            content: res.data.msg
                        });
                    }
                } else {
                    // 接口報錯
                    reject(response.data);
                }
            })
        })
    }
}
複製代碼

封裝axios請求以及配置代理

使用 create-react-app 建立的項目能夠直接在 package.json中配置 proxyios

"proxy": "http://xx.x.x.xx:port", // 服務器地址
複製代碼

定製 axiosweb

import axios from "axios";
import { Modal } from "antd";
const service = axios.create({
    timeout: 10000
})

// 請求攔截
service.interceptors.request.use(config => {
    console.log("config", config);
    config.headers["Authorization"] = "token"; // 通常接口請求的話須要帶上token
    return config;
}, error => {
    console.log("請求攔截error", error);
    Promise.reject(error);
})

service.interceptors.response.use(response => {
    let { data, statusText, status } = response;
    return {
    	statusText,
    	status,
    	data: JSON.parse(data) // 若是後端返回的數據是json序列化以後的數據須要解析
    }
}, error => {
    Modal.warning({
    	title: error.response.status,
    	content: error.response.statusText
    })
    Promise.reject(error);
})

export default service;

複製代碼

如何請求 (能夠封裝請求方法,好比 get 請求)ajax

import service from '../utils/request';
import { Modal } from 'antd';

export function ApiGet(url, params) {
    return new Promise((resolve, reject) => {
    	service.get(url, params)
    	    .then(res => {
            	if (res.status === 200) {
                    Modal.success({
                        title: res.status,
                        content: "請求成功!"
                    });
                    resolve(res);
            	} else {
                    Modal.warning({
                    	title: res.status,
                    	content: res.statusText
                    });
                    reject(res);
            	}
            })
            .catch(err => {
                console.log("err", err)
                Modal.warning({
                    title: "Error",
                    content: "請求錯誤!"
                })
                reject(err);
            });
    });
}
複製代碼

調用就很簡單了算法

ApiGet("接口").then(res => {
    console.log(res);
}, err => {

})
複製代碼
相關文章
相關標籤/搜索