React is not as easy to learn as Vue, from a learning standpoint. All things are difficult at the beginning, and then in the middle, the result is difficult…… Here is how I integrated the plug-in step by step and built the basic framework.
1 using the create – react – app
Create a project catalog using the official scaffolding tool
npx create-react-app react-app
Copy the code
The NPX in the first line is not a typo, it is the package runtime tool that comes with NPM 5.2+.
After the installation is complete, start the project using NPM or YARN
npm start(yarn start)
Copy the code
After the project is started, the default port number is 3000, which can be accessed through localhost:3000
Change the original catalog deconstruction, adjust to personal more accustomed or comfortable
2 Basic Configuration
2.1 Css preprocessors
Create-react-app does not expose configuration files by default. Running NPM run eject to expose configuration files is irreversible. Personally prefer to use react-app-rewired custom configuration (similar to vue-cli3 custom configuration file)
X react-app-rewired create-react-app 1.x react-app-rewired create-react-app 2.x react-app-rewired create-react-app 2.x react-app-rewired@^2.0.0+ The version needs to be used with customize-cra
2.1.1 support Scss
Create-react-app comes with sass-Loader and sass-related configurations. You only need to install Node-sass to use it
npm i node-sass -D
Copy the code
Note that the installation of Node-sass will always fail, NPM I node-sass is my preferred method to install all packages directly using CNPM –sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
2.1.2 support Less
Since antD will be integrated in the future, I recommend using less for the unified preprocessor, and execute:
npm i react-app-rewired customize-cra -D
Copy the code
Modify the package. The json
"scripts": {
"start": "react-app-rewired start"."build": "react-app-rewired build"."test": "react-app-rewired test"."eject": "react-scripts eject"
}
Copy the code
Then create config-overrides. Js in the root directory and add the configuration:
const { override, addLessLoader } = require('customize-cra')
const path = require('path')
module.exports = override(
addLessLoader()
)
Copy the code
2.2 Introduction of global common styles
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './common/style/reset.less'
import './common/style/base.less'
import './common/fonts/iconfont.css'
ReactDOM.render(<App />, document.getElementById('root'))
Copy the code
3 routing
Execute the installation command:
npm i react-router-dom
Copy the code
Modify app.jsx file:
import React, { Component } from 'react'
import { Router } from 'react-router-dom'
import history from './history'
import RouteConfig from './routes'
export default class App extends Component {
render() {
return (
<Router history= {history}>
<RouteConfig />
</Router>
)
}
}
Copy the code
BrowserRouter or HashRouter would normally be introduced. I use this scheme for non-component JS jump hacks (used when encapsulating HTTP request interceptors).
// history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory()
export default history
Copy the code
BaseLayout is a basic layout component that uses Suspense and lazy import() to load routes on demand (react version 16.6.0+ only supports this form)
//RouteConfig routes index.js import React, {Suspense} from'react'
import { Route, Switch } from 'react-router-dom'
import { Spin } from 'antd';
import BaseLayout from '.. /page/layout'
import Home from '.. /page/home'
import Login from '.. /page/login'
import NotFound from '.. /page/other/404'
import accounts from './accounts'
import loan from './loan'
const allRoutes = [
...accounts,
...loan
]
const Loading = () => {
return (
<div
className="loading"
style={{
paddingTop: '50px',
textAlign: 'center'
}}
>
<Spin size="large" />
</div>
)
}
export default () => {
return (
<Switch>
<Route path="/login" component={Login}></Route>
<Route path="/"render={(props) => ( <BaseLayout {... props}> <Suspense fallback={<Loading />}> <Switch> <Route exact path="/" component={Home} />
{
allRoutes.map((route, index) => <Route path={route.path} key={index} component={route.comp} />)
}
<Route path="*" component={NotFound} />
</Switch>
</Suspense>
</BaseLayout>
)}></Route>
</Switch>
)
}
Copy the code
4 Layout Basic Layout components
To import ANTD and reference it as needed, execute the command:
npm i antd
npm i babel-plugin-import -D
Copy the code
Modify config-overrides. Js file:
const { override, fixBabelImports, addLessLoader } = require('customize-cra')
const path = require('path')
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
addLessLoader()
)
Copy the code
Layout master file
import React, { Component } from 'react'
import { Layout } from 'antd'
import SiderBar from './siderbar'
import MainView from './mainView'
const { Sider } = Layout
export default class BaseLayout extends Component {
constructor() {
super()
this.state = {
collapsed: false,
}
}
onCollapse = (collapsed) => {
this.setState({
collapsed,
})
}
render() {
return (
<Layout className="layout">
<Sider
width="230px"
collapsible
className="layout-sider"
style={{
position: 'fixed',
left: '0',
top: '0',
bottom: '0',
paddingTop: '10px',
}}
onCollapse={this.onCollapse}
>
<div
className="iconfont icon-logo"
style={{
lineHeight: 1,
fontSize: this.state.collapsed ? '50px' : '100px',
color: '#fff',
textAlign: 'center',
}}
></div>
<p
className="layout-sider__desc"
style={{
paddingTop: '10px',
whiteSpace: 'nowrap',
color: '#fff',
textAlign: 'center',
}}
>
{this.state.collapsed ? 'jack ma' : 'Welcome, Jack Ma'}
</p>
<SiderBar pathname={this.props.location.pathname}></SiderBar>
</Sider>
<MainView collapsed={this.state.collapsed}>{this.props.children}</MainView>
</Layout>
)
}
}
Copy the code
5 Encapsulate the HTTP request
In Vue, I usually mount the encapsulated HTTP request on this. In React, I just reference whatever I need
5.1 axios instance
import axios from 'axios'
import defaultConfig from './config'
import { notification } from 'antd'
import history from '.. /history'
const axiosInstance = axios.create(defaultConfig)
axiosInstance.interceptors.request.use(
config => {
return config
},
error => {
console.log(error)
return Promise.reject(error)
}
)
axiosInstance.interceptors.response.use(
response => {
letdata = response.data ........................... . Interceptors in logic... notification.error({ message:'wrong',
description: data.message
})
}
return data
},
error => {
if (error.response) {
switch (error.response.status) {
case 500:
notification.error({
message: 'wrong',
description: 'Interface service error'
})
break
case 404:
notification.error({
message: 'wrong',
description: 'Interface does not exist'
})
break
case 403:
notification.error({
message: 'wrong',
description: 'User information expired'
})
history.push('/login')
break
case 401:
notification.error({
message: 'wrong',
description: 'Login expired'
})
break
default:
notification.error({
message: 'wrong',
description: 'Interface cannot connect'
})
break}}return Promise.reject(error)
}
)
export default axiosInstance
Copy the code
5.2 Encapsulated request functions
import axiosInstance from './axios'
export const GET = (url, params) => {
return axiosInstance({
method: 'get',
url,
params
}).then(res => {
return Promise.resolve(res)
}).catch(err => {
return Promise.reject(err)
})
}
export const POST = (url, data) => {
return axiosInstance({
method: 'post',
url,
data
}).then(res => {
return Promise.resolve(res)
}).catch(err => {
return Promise.reject(err)
})
}
Copy the code
5.3 API management
import { GET, POST } from '@/http'
export const doLogin = (data = {}) => {
return POST('Backend URL', data)
}
export const getMenuData = (params = {}) => {
return GET('Backend URL', params)
}
Copy the code
5.4 Page
. Omit the code import {getMenuData} from'@/api'
export default class Siderbar extends Component {
constructor() {
super()
this.state = {
menuTree: []
}
}
componentDidMount() {this.getmenu ()} getMenu = async () => {const menus = await getMenuData() // recursive loop out of the menu const menuTree = this.renderMenu(menus) this.setState({ menuTree, }) } }Copy the code
The last
1 Configure cross-domain
When create-react-app is lower than 2.0, it can be found in package.json:
"proxy": {"/manage": {"target":"http://test.xxx.com"."changeOrigin": true}}Copy the code
For create-react-app versions later than 2.0, only string can be configured in package.json, so run the following command to install:
npm i http-proxy-middleware -D
Copy the code
Create setupproxy.js in the SRC directory
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function (app) {
app.use('/api', createProxyMiddleware({
target: 'https://test.xxx.com',
changeOrigin: true,
secure: false,
pathRewrite: {
'/api': ' '}})); };Copy the code
2 Other Configurations
To configure the alias, modify config-overrides
const { override, fixBabelImports, addWebpackAlias, addLessLoader } = require('customize-cra')
const path = require('path')
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
addWebpackAlias({
[The '@']: path.resolve(__dirname, './src')
}),
addLessLoader()
);
Copy the code
Vue can use scoped to avoid global style contamination, while React uses objects directly in components or distinguishes between class names. To implement the CSS Module, modify the addLessLoader configuration in config-overrides
const { override, fixBabelImports, addWebpackAlias, addLessLoader } = require('customize-cra')
const path = require('path')
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
addWebpackAlias({
[The '@']: path.resolve(__dirname, './src')
}),
addLessLoader({
localIdentName: '[local]--[hash:base64:5]'}));Copy the code
Less and an error will be reported if the less loader version you installed is larger than 6.0