【React】React学习笔记3(React路由、Ant Design)

React学习笔记3(React路由、Ant Design)


零 l  说明


本文参考教程:[尚硅谷2021版React技术全家桶]

本文上接:
[React学习笔记1(React概念)]
[React学习笔记2(React脚手架、组件通信与网络请求库)]

本文顺序与视频不同,更适合学习过的复习,初学还是建议看视频






一 l  React 路由基础


react内置路由器库为React-Router库,其又细分为如下

  • react-router:核心组件
  • react-router-dom:应用于浏览器端开发的路由库(单独使用包含了react-router的核心部分)
  • react-router-native:应用于native端开发的路由

本文只涉及react-router-dom的使用

安装库(命令行下,脚手架默认没有安装):npm install react-router-dom --save


(一)【了解】一些概念

1、SPA(Single Page web Application 单页Web应用)

(1)整个应用只有一个完整的页面。
(2)点击页面中的链接不会刷新页面,只会做页面的局部更新。
(3)数据都需要通过ajax请求获取, 并在前端异步展现。

2、路由

path路径:指的是ip:端口后的路径。(如127.0.0.1:8080/home中的/home是路径)

  1. 什么是路由?
    (1) 一个路由就是一个映射关系(key:value)
    (2) key为路径, value可能是function或component

  2. 路由分类
    (1) 后端路由:
      a. 理解: value是function, 用来处理客户端提交的请求。
      b. 注册路由: router.get(path, function(req, res))
      c. 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
    (2) 前端路由:
      a. 浏览器端路由,value是component,用于展示页面内容。
      b. 注册路由:
      c. 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件

前端路由补充:
 1. 前端路由靠BOM(BrowserObjectModel浏览器对象模型)的history属性(浏览器的历史记录)实现。
 2. 存储BOM的history属性的容器是一个先入后出的栈
 3. 操作history属性有两种方法
   (1) let history = History.createBrowserHistory()直接使用H5推出的history身上的API,旧浏览器不兼容
   (2) let history = History.createHashHistory()使用hash值(锚点跳转),兼容性好,但是不推荐(丑)

3、路由组件与一般组件

路由器进行调用的组件称为路由组件。

 一般组件路由组件
写法不同<Demo/><Route path="/demo" component={Demo}/>
存放位置不同src/componentssrc/pages
接收到的props不同写组件标签时传递了什么,就能收到什么接收到路由器发送的三个固定的属性,如下

路由组件接收的props
history:
 go: ƒ go(n)
 goBack: ƒ goBack()
 goForward: ƒ goForward()
 push: ƒ push(path, state)
 replace: ƒ replace(path, state)
location:
 pathname: “/about”
 search: “”
 state: undefined
match:
 params: {}
 path: “/about”
 url: “/about”


(二)效果图

点击About或Home会跳转路由(一级路由)
点击Home下的Nerws和Message跳转路由(二级路由)
点击Message中信息跳转路由(三级路由)
1.2.2.1
1.2.2.2


(三)< BrowserRouter > 与 < HashRouter >

示例:src/index.js(引入路由器的一般写法)

// 引入react核心库
import React from 'react'
// 引入ReactDOM
import ReactDOM from 'react-dom'
// 引入路由器
import {BrowserRouter} from 'react-router-dom'
// 引入App
import App from './App'

ReactDOM.render(
 <BrowserRouter>
   <App/>
 </BrowserRouter>,
 document.getElementById('root')
)

BrowserRouter常用,HashRouter兼容好

 BrowserRouterHashRouter
底层原理BrowserRouter使用的是H5的history API(不是this.props.history),
不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值,
会把/#后的字符串转化为哈希值。
path表现形式BrowserRouter的路径中没有#,
例如:localhost:3000/demo/test
HashRouter的路径包含#,
例如:localhost:3000/#/demo/test
刷新后对路由state参数的影响BrowserRouter没有任何影响,因为state保存在history对象中。HashRouter刷新后会导致路由state参数的丢失!!!

备注:HashRouter直接调用前端资源,不会向后端发送请求;可以用于解决一些路径错误相关的问题。


(四)< Link > 、 < NavLink > 和 < Route >

  1. Link标签<Link to="/a">Demo</Link>,会把path改为localhost:3000/a
  2. NavLink标签在Link标签的基础之上,适配css样式显示高亮效果
  3. 展示区写Route标签进行路径的匹配<Route path='/a' component={Demo}/>,会匹配路径/a,展示Demo组件

1、< Link > 、< Route > 用法

public/index.html:略

src/App.jsx(不带样式)

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'

export default class App extends Component {
 render() {
   return (
     <div>
       <h2>React Router Demo</h2>
       {/* 在React中靠路由链接实现切换组件--编写路由链接 */}
       <Link className="list-group-item" to="/about">About</Link>
       <Link className="list-group-item" to="/home">Home</Link>
       {/* 注册路由 */}
       <Route path="/about" component={About}/>
       <Route path="/home" component={Home}/>
     </div>
   )
 }
}

src/pages/Home/index.jsx

import React, { Component } from 'react'
export default class Home extends Component {
 render() {
   return ( <h3>我是Home的内容</h3> )
 }
}

src/pages/About/index.jsx

import React, { Component } from 'react'
export default class About extends Component {
 render() {
   return ( <h3>我是About的内容</h3> )
 }
}

2、< NavLink > —— 选择标签高亮

(1)用法

<Link className="list-group-item" to="/about">About</Link>
<Link className="list-group-item" to="/home">Home</Link>

改为

<NavLink className="list-group-item" to="/about">About</Link>
<NavLink className="list-group-item" to="/home">Home</Link>

可以添加选中高亮效果。

  1. <NavLink>可以在选中的className后默认追加active表示高亮,同时bootstrap.css的样式认为有active的className就是高亮,所以这里可以显示正确。如果使用的是其他的样式库则不一定。
  2. <NavLink>activeClassName可以指定追加的className后缀

所以

<NavLink className="list-group-item" to="/about">About</Link>
<NavLink className="list-group-item" to="/home">Home</Link>

等价于

<NavLink activeClassName="active" className="list-group-item" to="/about">About</Link>
<NavLink activeClassName="active" className="list-group-item" to="/home">Home</Link>
(2)【了解】封装< NavLink >

每次用<NavLink>都要传activeClassNameclassName属性太麻烦,可以自己封装好这两个属性

src/App.jsx(不带样式)

import React, { Component } from 'react'
import {Route} from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'
import MyNavLink from './components/MyNavLink'

export default class App extends Component {
 render() {
   return (
     <div>
       <h2>React Router Demo</h2>
       {/* 在React中靠路由链接实现切换组件--编写路由链接 */}
       <MyNavLink to="/about">About</MyNavLink>
       <MyNavLink to="/home">Home</MyNavLink>
       {/* 注册路由 */}
       <Route path="/about" component={About}/>
       <Route path="/home" component={Home}/>
     </div>
   )
 }
}

src/components/MyNavLink/index.jsx

import React, { Component } from 'react'
import {NavLink} from 'react-router-dom'

export default class MyNavLink extends Component {
 render() {
   return (
     <NavLink activeClassName="active" className="list-group-item" {...this.props}/>
   )
 }
}

<MyNavLink to="/about">About</MyNavLink>为什么使用<NavLink activeClassName="active" className="list-group-item" {...this.props}/>就可以完全赋值?
 
About是作为标签体内容(<标签名 标签属性>标签体</标签名>)传入,标签体是一种特殊的标签属性,标签属性固定为children。

总结:

  1. NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
  2. 标签体内容是一个特殊的标签属性(children)
  3. 通过this.props.children可以获取组件标签的标签体内容
(3)样式丢失

现象:

  1. <MyNavLink to="/about">About</MyNavLink>写成<MyNavLink to="/abc/about">About</MyNavLink>,且<Route path="/about" component={About}/>写成<Route path="/abc/about" component={About}/>后,若在跳转后刷新页面,则可能造成样式丢失。

原因:

  1. 初始化时查找的是localhost:3000/css/bootstrap.css,显示正确;
    跳转多级页面刷新后查找的是localhost:3000/abc/css/bootstrap.css,找不到资源时会显示public/index.html,所以找到了public/index.html,虽然状态码是200,但不是css样式,而是html文件。

解决:

  1. 【常用】public/index.html中的<link rel="stylesheet" href="./css/bootstrap.css">
    改为<link rel="stylesheet" href="/css/bootstrap.css">(去掉路径里的点)
  2. 【常用】【React专属】public/index.html中的<link rel="stylesheet" href="./css/bootstrap.css">
    改为<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">(路径前加“%PUBLIC_URL%”)
  3. 【不常用】在App.jsx中使用<HashRouter>

(五)< Switch > —— 单一匹配

现象:

  1. 当存在如下代码且路径为/home时,路由器会顺序遍历路由,Home组件在上,Test组件在下。

src/App.jsx

...
 <Route path="/about" component={About}/>
 <Route path="/home" component={Home}/>
 <Route path="/home" component={Test}/>
...

问题:

  1. 首先同一路径我们希望只有一个组件(多个同路径组件可以合并).
  2. 希望路由器查找到路径后不再继续向下查找(性能问题)

解决:

  1. 最外面套一层<Switch>标签即可

src/App.jsx

...
 <Switch>
   <Route path="/about" component={About}/>
   <Route path="/home" component={Home}/>
   <Route path="/home" component={Test}/>
 </Switch>
...

(六)< Redirect > —— 重定向

  一般写在所有路由注册的最下方,当路由都没有命中时,跳转到<Redirect>指定的路由。

示例:默认展示/about

...
 <Switch>
   <Route path="/about" component={About}/>
   <Route path="/home" component={Home}/>
   <Redirect to="/about"/>
 </Switch>
...






二 l  React 路由高级


(一)路由的模糊匹配与精准匹配

(1)模糊匹配【默认】:
  1. <Route>的path属性值是<Link>的to属性值从头开始的(完全包含path属性值的)子串
<Link> to="?"<Route> path="?"是否匹配
/home/home
/home/a/b/home
/home/home/a/b
/a/home/b/home
(2)精准匹配开启方法【一般不开】:

严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

  1. <Route>标签加上exact={true}(简写exact
    用法:<Route exact={true} path="/about" component={About}/>
    简写:<Route exact path="/about" component={About}/>
<Link> to="?"<Route> path="?"是否匹配
/home/home
/home/a/b/home
/home/home/a/b
/a/home/b/home

(二)嵌套路由(二级路由、多级路由)

效果图:
1.3.1
注意事项:(其他的都跟单级路由类似)

  1. 注册子路由时要加上父路由的path值
  2. 路由的匹配是按照注册路由的顺序进行的(从最外层的App.jsx开始,一层一层的匹配)

1、主要代码:

src/App.jsx(不能开启精确模式)(不带样式)

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'

export default class App extends Component {
 render() {
   return (
     <div>
       <h2>React Router Demo</h2>
       {/* 在React中靠路由链接实现切换组件--编写路由链接 */}
       <Link className="list-group-item" to="/about">About</Link>
       <Link className="list-group-item" to="/home">Home</Link>
       {/* 注册路由 */}
       <Route path="/about" component={About}/>
       <Route path="/home" component={Home}/>
     </div>
   )
 }
}

src/pages/Home/index.jsx

import React, { Component } from 'react'
import MyNavLink from '../../components/MyNavLink'
import {Route,Switch,Redirect} from 'react-router-dom'
import News from './News'
import Message from './Message'

export default class Home extends Component {
 render() {
   return (
       <div>
         <h3>我是Home的内容</h3>
         <div>
           <ul className="nav nav-tabs">
             <li>
               <MyNavLink to="/home/news">News</MyNavLink>
             </li>
             <li>
               <MyNavLink to="/home/message">Message</MyNavLink>
             </li>
           </ul>
           {/* 注册路由 */}
           <Switch>
             <Route path="/home/news" component={News}/>
             <Route path="/home/message" component={Message}/>
             <Redirect to="/home/news"/>
           </Switch>
         </div>
       </div>
     )
 }

src/pages/Home/Message/index.jsx

import React, { Component } from 'react'
export default class Message extends Component {
 render() {
   return (
     <div>
       <ul>
         <li>
           <a href="/message1">message001</a>&nbsp;&nbsp;
         </li>
         <li>
           <a href="/message2">message002</a>&nbsp;&nbsp;
         </li>
         <li>
           <a href="/message/3">message003</a>&nbsp;&nbsp;
         </li>
       </ul>
     </div>
   )
 }
}

src/pages/Home/News/index.jsx

import React, { Component } from 'react'
export default class News extends Component {
 render() {
   return (
     <ul>
       <li>news001</li>
       <li>news002</li>
       <li>news003</li>
     </ul>
   )
 }
}

(三)向路由组件传递参数数据

一级路由跳转Home,二级路由跳转Message,三级路由跳转Detail

下面用法中的代码都是演示传递id和titile两个属性

1、传递params参数

  类似Ajax中传递使用的params参数

(1)用法
父组件:
  ...
    {/* 向路由组件传递params参数(携带参数) */}
    <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
  ...
    {/* 声明接收params参数(声明接收) */}
    <Route path="/home/message/detail/:id/:title" component={Detail}/>
  ...

子组件:
  ...
    // 接收params参数
    const {id,title} = this.props.match.params
  ...

tips:

  1. 子路由组件接收的参数从this.props.match.params中取
  2. <Route>中的:id:title是属性的key

2、传递search参数

  类似Ajax中的query参数

(1)用法
父组件:
  ...
    {/* 向路由组件传递search参数(携带参数) */}
    <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
  ...
    {/* search参数无需声明接收,正常注册路由即可 */}
    <Route path="/home/message/detail" component={Detail}/>
  ...

子组件:
  import qs from 'querystring'
  ...
    // 接收search参数
    // qs.parse: 将urlencode格式转化为json格式
    // search.slice(1): 去掉第一个"?"字符
    const {search} = this.props.location
    const {id,title} = qs.parse(search.slice(1))
  ...

tips:

  1. 子路由组件接收的参数从this.props.location.search中取
  2. 获取到的search是urlencoded编码字符串,需要借助querystring解析

3、传递state参数(不是组件中的state属性)

  类似Ajax中的query参数

(1)用法
父组件:
  ...
    {/* 向路由组件传递state参数(携带参数) */}
    <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>
  ...
    {/* state参数无需声明接收,正常注册路由即可 */}
    <Route path="/home/message/detail" component={Detail}/>
  ...

子组件:
  import qs from 'querystring'
  ...
    // 接收search参数
    const {id,title} = this.props.location.state || {}
  ...

tips:

  1. 子路由组件接收的参数从this.props.location.state中取
  2. 刷新也可以保留住参数(因为用的是BrowserRouter,会自动记录参数)

4、总结示例

src/pages/Home/Message/index.jsx

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Detail from './Detail'

export default class Message extends Component {
 state = {
   messageArr:[
     {id:'01',title:'消息1'},
     {id:'02',title:'消息2'},
     {id:'03',title:'消息3'},
   ]
 }
 render() {
   const {messageArr} = this.state
   return (
     <div>
       <ul>
         {
           messageArr.map((msgObj)=>{
             return (
               <li key={msgObj.id}>

                 {/* 向路由组件传递params参数 */}
                 {/* <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> */}

                 {/* 向路由组件传递search参数 */}
                 {/* <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> */}

                 {/* 向路由组件传递state参数 */}
                 <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>

               </li>
             )
           })
         }
       </ul>
       <hr/>
       {/* 声明接收params参数 */}
       {/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}

       {/* search参数无需声明接收,正常注册路由即可 */}
       {/* <Route path="/home/message/detail" component={Detail}/> */}

       {/* state参数无需声明接收,正常注册路由即可 */}
       <Route path="/home/message/detail" component={Detail}/>

     </div>
   )
 }
}

src/pages/Home/Message/Detail/index.jsx

import React, { Component } from 'react'
import qs from 'querystring'

const DetailData = [
 {id:'01',content:'01内容'},
 {id:'02',content:'02内容'},
 {id:'03',content:'03内容'}
]
export default class Detail extends Component {
 render() {
   console.log(this.props);

   // 接收params参数
   // const {id,title} = this.props.match.params 

   // 接收search参数
   // const {search} = this.props.location
   // const {id,title} = qs.parse(search.slice(1))

   // 接收state参数
   const {id,title} = this.props.location.state || {}

   const findResult = DetailData.find((detailObj)=>{
     return detailObj.id === id
   }) || {}
   return (
     <ul>
       <li>ID:{id}</li>
       <li>TITLE:{title}</li>
       <li>CONTENT:{findResult.content}</li>
     </ul>
   )
 }
}

(四)【了解】新页面在历史记录上的push与replace模式

1、push模式【默认】:

  push模式下 路由产生的新页面 会作为一个新结点 push进历史记录栈

例子:

  1. 先后进入:localhost:3000localhost:3000/homelocalhost:3000/home/massagelocalhost:3000/home/massage/1
  2. 栈中的数据顺序(自底向上):localhost:3000localhost:3000/homelocalhost:3000/home/massagelocalhost:3000/home/massage/1
  3. 出栈的顺序就是localhost:3000/home/massage/1localhost:3000/home/massagelocalhost:3000/homelocalhost:3000

2、replace模式开启方法:

  replace模式下 路由产生的新页面 会作为一个新结点 替换历史记录栈中存在的最新的结点
    开启:<Link replace={true} to="省略"></Link>
    简写为:<Link replace to="省略"></Link>

例子:在/home/massage/index.jsx中配置replace的情况

  1. 先后进入:localhost:3000localhost:3000/homelocalhost:3000/home/massagelocalhost:3000/home/massage/1
  2. 栈中的数据顺序(自底向上):localhost:3000localhost:3000/homelocalhost:3000/home/massage/1
  3. 出栈的顺序就是localhost:3000/home/massage/1localhost:3000/homelocalhost:3000

解释:所有massage的子组件的跳转在历史记录栈中都会替换掉最新的


(五)编程式路由导航(调用this.props.history上的API)

效果:
在这里插入图片描述

1、概念

借助this.prosp.history对象上的API对操作路由跳转、前进、后退

方法参数作用
this.prosp.history.push()path路由路径, state状态参数push方法跳转path指定的页面
this.prosp.history.replace()path路由路径, state状态参数replace方法跳转path指定的页面
this.prosp.history.goBack()无参数回退到上一页面
this.prosp.history.goForward()无参数前进到下一页面
this.prosp.history.go()n步长n>0, 前进n个页面;
n<0, 后退n个页面;
n=0, 无变化

2、主要代码

src/pages/Home/Message/index.jsx

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Detail from './Detail'

export default class Message extends Component {
 state = {
   messageArr:[
     {id:'01',title:'消息1'},
     {id:'02',title:'消息2'},
     {id:'03',title:'消息3'},
   ]
 }

 replaceShow = (id,title)=>{
   //replace跳转+携带params参数
   //this.props.history.replace(`/home/message/detail/${id}/${title}`)

   //replace跳转+携带search参数
   // this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)

   //replace跳转+携带state参数
   this.props.history.replace(`/home/message/detail`,{id,title})
 }

 pushShow = (id,title)=>{
   //push跳转+携带params参数
   // this.props.history.push(`/home/message/detail/${id}/${title}`)

   //push跳转+携带search参数
   // this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)

   //push跳转+携带state参数
   this.props.history.push(`/home/message/detail`,{id,title})
 }

 back = ()=>{ this.props.history.goBack() }

 forward = ()=>{ this.props.history.goForward() }

 go = ()=>{ this.props.history.go(-2) }

 render() {
   const {messageArr} = this.state
   return (
     <div>
       <ul>
         {
           messageArr.map((msgObj)=>{
             return (
               <li key={msgObj.id}>
                 {/* 向路由组件传递params参数 */}
                 {/* <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> */}

                 {/* 向路由组件传递search参数 */}
                 {/* <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> */}

                 {/* 向路由组件传递state参数 */}
                 <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>

                 &nbsp;<button onClick={()=> this.pushShow(msgObj.id,msgObj.title)}>push查看</button>
                 &nbsp;<button onClick={()=> this.replaceShow(msgObj.id,msgObj.title)}>replace查看</button>
               </li>
             )
           })
         }
       </ul>
       <hr/>
       {/* 声明接收params参数 */}
       {/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}

       {/* search参数无需声明接收,正常注册路由即可 */}
       {/* <Route path="/home/message/detail" component={Detail}/> */}

       {/* state参数无需声明接收,正常注册路由即可 */}
       <Route path="/home/message/detail" component={Detail}/>

       <button onClick={this.back}>回退</button>&nbsp;
       <button onClick={this.forward}>前进</button>&nbsp;
       <button onClick={this.go}>go</button>
     </div>
   )
 }
}

3、withRouter —— 给一般组件加上路由组件特有API

  withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
  withRouter的 返回值 是一个新组件

src/components/Header/index.jsx:主要看最后一行,使用withRouter暴露组件Header

import React, { Component } from 'react'
import {withRouter} from 'react-router-dom'

class Header extends Component {

 back = ()=>{
   this.props.history.goBack()
 }

 forward = ()=>{
   this.props.history.goForward()
 }

 go = ()=>{
   this.props.history.go(-2)
 }

 render() {
   console.log('Header组件收到的props是',this.props);
   return (
     <div className="page-header">
       <h2>React Router Demo</h2>
       <button onClick={this.back}>回退</button>&nbsp;
       <button onClick={this.forward}>前进</button>&nbsp;
       <button onClick={this.go}>go</button>
     </div>
   )
 }
}

export default withRouter(Header)






三 l  React UI 组件库


(一)一些概念

组件库是别人写好的包含样式的组件

  1. ant-design(国内蚂蚁金服,简称antd)
    (1) 官网: https://ant.design/index-cn
    (2) Github: https://github.com/ant-design/ant-design/
    (3) 安装:npm i install antd --save

  2. material-ui(国外)
    (1) 官网: http://www.material-ui.com/#/
    (2) Github: https://github.com/callemall/material-ui

  3. element ui (国内饿了么)
    (1) 官网:https://element.eleme.cn/#/zh-CN
    (2) Github:https://github.com/ElemeFE/element
    (3) 安装:npm i element-react --save

  4. vant ui(国内有赞,手机端比较好看)
    (1) 官网:https://vant-contrib.gitee.io/vant/#/zh-CN/
    (2) Github:https://github.com/mxdi9i7/vant-react
    (3) Gitee:https://gitee.com/vant-contrib/vant#https://github.com/mxdi9i7/vant-react
    (4) 安装:npm i vant-react --save


(二)简单使用ant-design

官网使用方法(因为官网的文档肯定比这里随便列的全):[视频链接]


(三)ant-design高级

1、按需引入样式+自定主题(新版本操作与课程内容已经不同了)

一般使用要在文件头加入import 'antd/dist/antd.css',这样会把所有的样式都引入,有很多不需要的样式
官网对应链接:https://ant.design/docs/react/use-with-create-react-app-cn

(1)3.x版本
  1. 安装依赖:npm install react-app-rewired customize-cra babel-plugin-import less less-loader --save
  2. 修改package.json
....
    "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test",
        "eject": "react-scripts eject"
    },
....
  1. 根目录下创建config-overrides.js
//配置具体的修改规则
const { override, fixBabelImports, addLessLoader } = require('customize-cra');
module.exports = override(
  // 按需导入
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: true,
  }),
  // 修改less主体颜色
  addLessLoader({
    lessOptions: {  // 操作less
    javascriptEnabled: true,  // 允许用js修改底层less文件
    modifyVars: { '@primary-color': 'blue' },  // 修改变量:  { '主色调': '蓝色' }(颜色可以使用单词和RGB)
    }
  }),
);
  1. 备注:不用在组件里亲自引入样式了,即:import 'antd/dist/antd.css'应该删掉
(2)【推荐】4.x版本
  1. 安装依赖:npm install @craco/craco babel-plugin-import less less-loader --save
  2. 修改package.json
....
    "scripts": {
        "start": "craco start",
        "build": "craco build",
        "test": "craco test",
        "eject": "react-scripts eject"
    },
....
  1. 根目录下创建config-overrides.js
const CracoLessPlugin = require('craco-less');

module.exports = {
  babel: {
    plugins: [
      ['import',  // 按需引入样式。插件名babel-plugin-import说明了在配置中的位置是babel、plugins、import
        {
          libraryName: 'antd',  // 针对antd库
          libraryDirectory: "es",  // 使用es模块化规范
          style: true  // 针对less生成的css文件进行按需引入(true比"css"用途更广一些)
        }]
    ]
  },
  plugins: [
    {
      plugin: CracoLessPlugin,  // craco的修改.less文件的插件(修改主题颜色)
      options: {
        lessLoaderOptions: {  // .less文件操作加载器
          lessOptions: {  // 操作.less文件
            modifyVars: {'@primary-color': '#00f'},  // 修改变量:  { '主色调': '蓝色' }(颜色可以使用单词和RGB)
            javascriptEnabled: true,  // 允许使用js修改.less文件
          }
        }
      }
    }]
};
  1. 备注:不用在组件里亲自引入样式了,即:import 'antd/dist/antd.css'应该删掉
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值