react官方文档https://zh-hans.reactjs.org
使用脚手架快速搭建React项目
create-react-app是Facebook官方推出的脚手架,基本可以零配置搭建基于webpack的React开发环境
步骤:
打开控制台
进入你想要创建项目的目录文件下面
依次执行以下命令
npm install -g create-react-app /*安装全局的脚手架*/
create-react-app my-demo /*创建项目 my-demo是项目名字*/
cd my-demo /*进入目录 然后启动*/
npm start
其他一些常用模块
npm install react-router-dom --save /*react路由*/
npm install react-loadable --save /*异步加载路由*/
npm install node-sass --save-dev /*sass文件样式*/
npm install axios --save /*数据请求*/
npm install redux react-redux --save-dev /*状态管理*/
npm install antd --save /*基于react的一个UI库,等同于vue的element ui*/
npm install svg-sprite-loader -D /*使用svg图标*/
修改webpack配置
方案一:通过craco插件修改配置
安装craco插件
npm install @craco/craco --save
修改package.json中运行命令
在项目根目录新建craco.config.js文件并进行配置
方案二:直接运行npm run eject反编译项目
使用'@'作为src文件
1.$npm run eject
2.在config/webpack.config.js文件的alias中插入代码'@': path.resolve('src')
路由配置
普通写法:直接在app.js里写路由配置
安装react-router-dom路由插件,react-router-dom 中文文档
npm install react-router-dom --save
在app.js里配置路由地址
// import { BrowserRouter, Route, NavLink, Link, Switch, Redirect } from 'react-router-dom'
import { HashRouter, Route, NavLink, Link, Switch, Redirect } from 'react-router-dom'
import Home from '@/views/home'
import Err404 from '@/views/err404'
function App() {
return (
<HashRouter>
<main className="body-main">
<Switch>
<Redirect exact from="/" to="/home" />
<Route path="/home" component={Home} />
<Route path="/404" exact component={Err404} />
<Redirect to="/404" />
</Switch>
</main>
<footer className="body-footer">
<NavLink to="/find" activeClassName="footer-active">底部导航1</NavLink>
<NavLink to="/find1" activeClassName="footer-active">底部导航2</NavLink>
<NavLink to="/find2" activeClassName="footer-active">底部导航3</NavLink>
</footer>
</HashRouter>
)
}
export default App;
BrowserRouter与HashRouter:BrowserRouter地址栏没有#,是需要服务端配合解析路由。 HashRouter地址栏有#,不需要服务端配合,是浏览器端解析路由。
Switch:它作用是一旦匹配到某个路径,就立即停止在向下匹配,并渲染该路径对应的组件,和js中switch...case的逻辑差不多
NavLink与Link:都是路径跳转组件,它们的区别在于NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
Redirect:该组件就是,重定向路径(路径不匹配,或者只有访问的是某个路径时,才进行跳转,也就是 from 和 to 混用)。一般写在所有路由注册的最下方,当所有路由都无法匹配时,重定向到Redirect指定的路由
Route:该组件有几个属性。path为路由url地址。component指定路由对应的组件路径。exact属性表示精确匹配path
进阶写法:分离代码,实现路由模块化
我们在项目根目录创建router/index.js存放分离出来的路由配置,并对app.js进行改写。代码如下
// router/index.js文件
import Loadable from 'react-loadable'
import Loading from '@/components/loading'
const routes = [
{
path: '/home',
component: Loadable({
loader: () => import('@/views/home'),
loading: Loading
})
},
{
path: '/user',
component: Loadable({
loader: () => import('@/views/user'),
loading: Loading
}),
children: [
{
path: '/user/',
component: Loadable({
loader: () => import('@/views/user/list'),
loading: Loading
})
},
{
path: '/user/userAdd',
component: Loadable({
loader: () => import('@/views/user/add'),
loading: Loading
})
}
]
},
{
path: '/404',
component: Loadable({
loader: () => import('@/views/err404'),
loading: Loading
})
},
]
export default routes
// app.js文件
import routers from './router' // 引入配置文件
// 改造Switch片段里的代码
<Switch>
<Redirect exact from="/" to="/home" />
{
routers.map((item, key) => {
return <Route key={key} path={item.path} exact={!!item.exact && (!item.children || !item.children.length)} render={props => (
<item.component {...props} routers={item.children} />
)} />
})
}
<Redirect to="/404" />
</Switch>
// user/index.js文件
function User(props) {
return (
<div>这是用户管理页面</div>
<div>
{
props.routers.map((item, key) => {
return <Route key={key} path={item.path} exact={!!item.exact && (!item.children || !item.children.length)} render={props => (
<item.component {...props} routers={item.children} />
)} />
})
}
</div>
)
}
export default User
// router/index.js文件
import React from 'react'
const routes = [
{
path: '/home',
component: React.lazy(() => import('@/views/home'))
}
]
export default routes
// app.js文件
import routers from './router'
import { Suspense } from 'react'
<Switch>
<Suspense fallback={<div>loading</div>}>
{
routers.map((item, key) => { ... })
}
</Suspense>
</Switch>
react中页面跳转
1.使用Link标签跳转
import { Link } from 'react-router-dom'
<Link to="/home">首页</Link>
2.js事件跳转
<span onClick={e => props.history.push('/home')}>首页</span>
3.返回上一页
<span onClick={e => props.history.goBack()}>返回</span>
React如何优雅的使用svg图标组件
参考文章:react项目中如何优雅的使用 svg
1.安装 svg-sprite-loader
npm i svg-sprite-loader -D
2.配置 /config/webpack.config.js
3.创建 /src/assets/icons/svg文件夹、/src/assets/icons/index.js文件
// src/assets/icons/index.js文件
const requireAll = requireContext => requireContext.keys().map(requireContext);
const svgs = require.context("./svg", false, /.svg$/);
requireAll(svgs);
// src/index.js文件
import "@/assets/icons";
4.创建 /src/components/SvgIcon组件,并在SvgIcon目录下添加index.js文件
// src/components/SvgIcon/index.js文件
import React from "react"
import PropTypes from "prop-types"
const svgClass = {
display: 'inline-block',
overflow: 'hidden',
fontSize: '14px',
minWidth: '14px',
width: '1em',
height: '1em'
}
const SvgIcon = props => {
const { iconClass, fill, style } = props
const currStyle = Object.assign({}, svgClass, style)
return (
<i aria-hidden="true" className="anticon">
<svg style={currStyle}>
<use xlinkHref={"#icon-" + iconClass} fill={fill} />
</svg>
</i>
)
}
SvgIcon.propTypes = {
iconClass: PropTypes.string.isRequired,
fill: PropTypes.string
}
SvgIcon.defaultProps = {
fill: "currentColor",
style: {}
}
export default SvgIcon
5.使用组件
import SvgIcon from "@/components/SvgIcon";
const searchIcon = {
fontSize: '20px'
}
const Demo = () => {
return <SvgIcon style={searchIcon} iconClass="search" fill="#8a8a8a" />
};
export default Demo
React创建组件
类组件
import React from "react"
export class MyDemo extends React.Component {
// 这里只列举几个常用的生命周期回调。更多回调请查看官网文档
constructor(props) {
// 类的构造函数,初始化state、方法绑定等
super(props);
this.state = {opacity: 1.0};
}
componentDidMount() {
// 组件首次渲染完成。PS:从服务器获取数据之类的一般写在这个回调里
}
componentDidUpdate() {
// 在组件完成更新后立即调用,首次渲染不会执行此方法。PS:如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求。
}
componentWillUnmount() {
// 销毁组件前调用
}
render() {
// 渲染组件
return (<div>组件的html代码</div>)
}
}
export default MyDemo
函数组件
函数组件中不存在state状态和生命周期回调,我们需要通过 React Hook 实现。详细介绍请查看文章React函数组件使用State和生命周期方法
import React, { useState, useEffect } from 'react';
function MyDemo(props) {
const [data, setData] = useState({ opacity: 1.0 }); // 等价于类组件中的 this.state = {data: {opacity: 1.0}}。setData为赋值data的函数
useEffect(() => {
console.log('首次渲染')
return () => {
console.log('即将卸载')
}
}, [])
return (<div>组件的html代码</div>)
}
export default MyDemo
使用redux状态管理
// 安装命令
npm install redux react-redux --save-dev
// 新建/store/index.js
import { createStore } from 'redux'
const defaultState = {
r_scrollAuto: false, // 框架.body-main的-webkit-overflow-scrolling样式
}
export default createStore((state, action) => {
switch (action.type) {
case 'SCROLLAUTO':
return Object.assign({}, state, {r_scrollAuto: action.auto})
default:
return state
}
}, defaultState)
// 修改App.js
import { Provider } from 'react-redux'
import store from '@/store'
function App() {
return (
<provider store={store}>
<hashrouter>
// ...其他代码...
</hashrouter>
</provider>
)
}
// 组件中使用(User组件为例)
import { useDispatch, useSelector } from 'react-redux'
function User(props) {
const auto = useSelector(state => state.r_scrollAuto)
const dispatch = useDispatch()
return <button click={e => dispatch({type: 'SCROLLAUTO', auto: !auto})}>点击</button>
}
使用mockjs模拟api请求
1.安装mockjs
npm i mockjs -D
2.src目录下新建mock/index.js
import Mock from 'mockjs'
// 首页banner
Mock.mock('/api/getBannerList', 'get', {
success: true,
message: '',
data: [
'https://bpic.588ku.com/element_banner/20/21/08/c413e5f6d74e67fe079a2116be950ebe.png!/unsharp/true/compress/true',
'https://bpic.588ku.com/element_banner/20/21/08/369b331152285e2b37f74acef79ea413.png!/unsharp/true/compress/true'
]
})
// 热卖推荐
Mock.mock('/api/hotRecommend', 'get', {
success: true,
message: '',
data: [
{
id: 1,
name: '商品1',
img: 'https://bpic.588ku.com/element_banner/20/21/08/c413e5f6d74e67fe079a2116be950ebe.png!/unsharp/true/compress/true'
}
]
})
export default Mock
3.引入并请求数据
import '@/mock'
import axios from 'axios'
axios.get('/api/getBannerList').then(result => {
console.log(result)
}, err => {
console.log(err)
})
自己常用的项目结构
├── config --------------------webpack配置
├── public --------------------出口
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── src ----------------------源码目录
│ ├── api ----------------------API目录
│ │ ├── api.js
│ │ └── server.js
│ ├── assets -----------------------资源目录
│ │ ├── style
│ │ ├── image
│ │ └── icons
│ ├── components -------------------公共组件
│ ├── index.js --------------------入口
│ ├── views --------------------页面目录
│ ├── router -----------------------路由
│ │ └── index.js
│ ├── store ------------------------react-redux状态管理目录
│ │ ├── store.js
│ │ └── user
│ └── utils ------------------------公用方法
│ ├── request.js ---------------异步加载组件
│ └── commons.js ---------------公用方法
├── package-lock.json
├── package.json --------------------项目package.json
└── README.md ----------------------README