React脚手架应用(二)

news2024/11/19 10:43:45

1、react脚手架

脚手架简介
用来帮助程序员快速创建一个基于xxx库的模板项目
1、包含了所有需要的配置(语法检查、jsx编译、devServer…);
2、下载好了所有相关的依赖;
3、可以直接运行一个简单效果;

create-react-app
1、react提供了一个用于创建react项目的脚手架库: create-react-app
2、项目的整体技术架构为:react + webpack + es6 + eslint
3、使用脚手架开发的项目的特点:模块化、组件化、工程化;

创建项目并启动
第一步,全局安装:npm i -g create-react-app
第二步,切换到想创项目的目录,使用命令:create-react-app hello-react
第三步,进入项目文件夹:cd hello-react
第四步,启动项目:npm start

react脚手架项目结构
在这里插入图片描述

2、React样式隔离

2.1、样式问题叙述

在components下创建两个文件HelloWelcone分别在两个文件夹内创建index.jsindex.css文件;
在这里插入图片描述
App.js注册引入HelloWelcone组件

//App.js
import './App.css';  
import Hello from './components/Hello'  //引入Hello组件
import Welcome from './components/Welcome' //引入Welcome组件
function App() {
  return (
    <div className="App">
      <Hello/>    //注册Hello组件  这里hello是先注册的
      <Welcome/>     //注册Welcome组件    welcome是后注册的 记住这是要考的哦
    </div>
  );
}

export default App;

Hello组件

//Hello/index.js文件
import React, {Component} from "react";
import "./index.css"
export default class Hello extends Component {
    render() {
        return <h2 className="title"> Hello React</h2>
    }
}

//Hello/index.css文件
.title{
    background-color: red;
}

Welcome组件同理,除了h2标签中文字不同 及 title的背景色为蓝色

启动项目
在这里插入图片描述
预期结果:上面为红色,下面为蓝色;
实际结果:都是蓝色,产生样式污染;

因为react组件在页面渲染的前,会将组件的样式“集合”到一起,因为引用组件时,<Welcome/>组件在<Home/>下面,因此<Welcome/>组件的蓝色会覆盖<Home/>组件的红色。

2.2、样式问题处理

1、Css Modules
Css Modules 并不是React专用解决方法,适用于所有使用 webpack 等打包工具的开发环境。

使用如下:

// 1、更改index.css文件名为index.module.css
//index.module.css文件
.bg {
	padding: 20px;
    background-color: red;
}

// 驼峰命名
.headName {
    background-color: green;
}

// 下划线
.head_age {
	background-color: skyblue;
}

// 连接符
.head-gender {
	background-color: orange;
}

.size {
    font-size: 20px;
}

// ':global' 表示该类为全局作用域下的
:global .text-left {
	color: pink;
    float: left;
}


// 2、修改Hello/index.js文件引入方式
import React, {Component} from "react";
//不可以import "./index.module.css" 这样引入
import hello from "./index.module.css"  //改变引入方法  
export default class Hello extends Component {
    render() {
        return (
	        <div className={hello.bg}>
				<h2 className={hello.headName}>我叫张三</h2>
				<h2 className={hello.head_age}>年龄19</h2>
				
				// 类名使用 - 连接符写法如下:
				<h2 className={hello.headGender}>性别男</h2>
				// 或
				<h2 className={hello['head-gender']}>性别男</h2>
				
				// 多类名用法
				<div className={`${hello['head-gender']} ${hello.size}`}></div>
				
				// className="text-left" 这种形式则表示全局下的选择器
		        <p className="text-left">全局样式---全局样式</p>
			</div>	
		)
    }
}

css-modules方案,每个className都需要写一个styles.实在是麻烦

2、scss的嵌套语法和CSS 属性选择器
安装sass:npm install node-sass --save-dev

Person组件

// 1、Person/index.js文件
import React, {Component} from "react";
import './index.scss'

export default class Person extends React.Component{
  render() {
    return (
      <div data-component='person'>
        <p className="name">person组件</p>
        <p className="text">隔离css</p>
      </div>
    )
  }
}

// 2、Person/index.scss文件
[data-component=person] {
  padding: 20px;
  background-color: #761c19;
  .name{
    font-size: 18px;
    color: #1b6d85;
  }
  .text {
    color: #3c763d;
  }
}

data-component可以限制为每个组件的名字,因为className可能会出现重复,但是组件名字在同一个项目中基本不会重复。

这样就解决了css class全局污染的问题。简单易用,不用引入新的概念和扩展。

3、React代理配置

前端本地端口3000, 后端服务本地端口5000,配置代理

3.1、方法一

在package.json中追加如下配置
"proxy": "http://localhost:5000"

优点:配置简单,前端请求资源时可以不加任何前缀。
缺点:不能配置多个代理。
工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)

import React, { Component } from 'react'
import axios from 'axios'

export default class App extends Component {

	getStudentData = ()=>{
		axios.get('http://localhost:3000/students').then(
			response => {console.log('成功了',response.data);},
			error => {console.log('失败了',error);}
		)
	}

	getCarData = ()=>{
		axios.get('http://localhost:3000/cars').then(
			response => {console.log('成功了',response.data);},
			error => {console.log('失败了',error);}
		)
	}

	render() {
		return (
			<div>
				<button onClick={this.getStudentData}>点我获取学生数据</button>
				<button onClick={this.getCarData}>点我获取汽车数据</button>
			</div>
		)
	}
}

3.2、方法二

第一步:在src下创建配置文件:src/setupProxy.js
编写setupProxy.js配置具体代理规则:

const proxy = require('http-proxy-middleware')

module.exports = function(app) {
  app.use(
    proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
      target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
      changeOrigin: true, //控制服务器接收到的请求头中host字段的值
      /*
      	changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
      	changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
      	changeOrigin默认值为false,但我们一般将changeOrigin值设为true
      */
      pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
    }),
    proxy('/api2', { 
      target: 'http://localhost:5001',
      changeOrigin: true,
      pathRewrite: {'^/api2': ''}
    })
  )
}

优点:可以配置多个代理,可以灵活的控制请求是否走代理。
缺点:配置繁琐,前端请求资源时必须加前缀。

import React, { Component } from 'react'
import axios from 'axios'

export default class App extends Component {

	getStudentData = ()=>{
		axios.get('http://localhost:3000/api1/students').then(
			response => {console.log('成功了',response.data);},
			error => {console.log('失败了',error);}
		)
	}

	getCarData = ()=>{
		axios.get('http://localhost:3000/api2/cars').then(
			response => {console.log('成功了',response.data);},
			error => {console.log('失败了',error);}
		)
	}

	render() {
		return (
			<div>
				<button onClick={this.getStudentData}>点我获取学生数据</button>
				<button onClick={this.getCarData}>点我获取汽车数据</button>
			</div>
		)
	}
}

4、消息订阅-发布机制

工具库:PubSubJS
下载:npm install pubsub-js --save

使用:
1、import PubSub from 'pubsub-js' 引入依赖
2、PubSub.publish('delete', data) 发布消息
3、PubSub.subscribe('delete', function(data){}) 订阅消息

Search组件与List组件为同级组件,当Search组件中点击获取数据时发布消息,在List组件中接收消息中数据,渲染界面;

Search组件

import React, { Component } from 'react'
import PubSub from 'pubsub-js'
import axios from 'axios'

export default class Search extends Component {

	search = ()=>{
		//获取用户的输入(连续解构赋值+重命名)
		const {keyWordElement:{value:keyWord}} = this
		//发送请求前通知List更新状态
		PubSub.publish('atguigu',{isFirst:false,isLoading:true})
		//发送网络请求
		axios.get(`/api1/search/users?q=${keyWord}`).then(
			response => {
				//请求成功后通知List更新状态
				PubSub.publish('atguigu',{isLoading:false,users:response.data.items})
			},
			error => {
				//请求失败后通知App更新状态
				PubSub.publish('atguigu',{isLoading:false,err:error.message})
			}
		)
	}

	render() {
		return (
			<section className="jumbotron">
				<h3 className="jumbotron-heading">搜索github用户</h3>
				<div>
					<input ref={c => this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/>&nbsp;
					<button onClick={this.search}>搜索</button>
				</div>
			</section>
		)
	}
}

List组件

import React, { Component } from 'react'
import PubSub from 'pubsub-js'
import './index.css'

export default class List extends Component {

	state = { //初始化状态
		users:[], //users初始值为数组
		isFirst:true, //是否为第一次打开页面
		isLoading:false,//标识是否处于加载中
		err:'',//存储请求相关的错误信息
	} 

	componentDidMount(){
		this.token = PubSub.subscribe('atguigu',(_,stateObj)=>{
			this.setState(stateObj)
		})
	}

	componentWillUnmount(){
		PubSub.unsubscribe(this.token)
	}

	render() {
		const {users,isFirst,isLoading,err} = this.state
		return (
			<div className="row">
				{
					isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
					isLoading ? <h2>Loading......</h2> :
					err ? <h2 style={{color:'red'}}>{err}</h2> :
					users.map((userObj)=>{
						return (
							<div key={userObj.id} className="card">
								<a rel="noreferrer" href={userObj.html_url} target="_blank">
									<img alt="head_portrait" src={userObj.avatar_url} style={{width:'100px'}}/>
								</a>
								<p className="card-text">{userObj.login}</p>
							</div>
						)
					})
				}
			</div>
		)
	}
}

5、React路由

5.1、相关理解

SPA的理解
1、单页Web应用(single page web application,SPA);
2、整个应用只有一个完整的页面;
3、点击页面中的链接不会刷新页面,只会做页面的局部更新;
4、数据都需要通过ajax请求获取,并在前端异步展现;

后端路由
1、理解: value是function,用来处理客户端提交的请求;
2、注册路由: router.get(path, function(req, res));
3、工作过程:当node接收到一个请求时,根据请求路径找到匹配的路由,调用路由中的函数来处理请求,返回响应数据;

前端路由
1、浏览器端路由,value是component,用于展示页面内容;
2、注册路由:<Route path="/test" component={Test}>
3、工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件

5.2、react-router-dom

react的一个插件库,专门用来实现一个SPA应用,基于react的项目基本都会用到此库。

使用:
下载react-router-domnpm install --save react-router-dom
引入bootstrap.css:<link rel="stylesheet" href="/css/bootstrap.css">

5.3、路由基本使用

1、导航区的a标签改为Link标签<Link to="/xxxxx">Demo</Link>
2、展示区写Route标签进行路径的匹配<Route path='/xxxx' component={Demo}/>
3、<App>的最外侧包裹了一个<BrowserRouter><HashRouter>

App组件

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

export default class App extends Component {
	render() {
		return (
			<div>
				<div className="row">
					<div className="col-xs-2 col-xs-offset-2">
						<div className="list-group">

							{/* 原生html中,靠<a>跳转不同的页面 */}
							{/* <a className="list-group-item" href="./about.html">About</a>
							<a className="list-group-item active" href="./home.html">Home</a> */}

							{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
							<Link className="list-group-item" to="/about">About</Link>
							<Link className="list-group-item" to="/home">Home</Link>
						</div>
					</div>
					<div className="col-xs-6">
						<div className="panel">
							<div className="panel-body">
								{/* 注册路由 */}
								<Route path="/about" component={About}/>
								<Route path="/home" component={Home}/>
							</div>
						</div>
					</div>
				</div>
			</div>
		)
	}
}

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')
)

5.4、NavLink与封装NavLink

NavLink可以实现当前路由标签高亮效果,Link标签无法实现高亮效果
1、通过activeClassName指定高亮效果样式名;
2、标签体内容是一个特殊的标签属性;
3、通过this.props.children可以获取标签体内容;

MyNavLink组件

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

export default class MyNavLink extends Component {
	render() {
		// console.log(this.props);
		
		// this.props.children可以获取标签体内容
		// {to: "/about", children: "About"}
		return (
			<NavLink activeClassName="aaabbb" className="list-group-item" {...this.props}/>
		)
	}
}

App组件

import React, { Component } from 'react'
import {Route} from 'react-router-dom'
import Home from './pages/Home' //Home是路由组件
import About from './pages/About' //About是路由组件
import Header from './components/Header' //Header是一般组件
import MyNavLink from './components/MyNavLink'

export default class App extends Component {
	render() {
		return (
			<div>
				<div className="row">
					<div className="col-xs-2 col-xs-offset-2">
						<div className="list-group">
							{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
							<MyNavLink to="/about">About</MyNavLink>
							<MyNavLink to="/home">Home</MyNavLink>
						</div>
					</div>
					<div className="col-xs-6">
						<div className="panel">
							<div className="panel-body">
								{/* 注册路由 */}
								<Route path="/about" component={About}/>
								<Route path="/home" component={Home}/>
							</div>
						</div>
					</div>
				</div>
			</div>
		)
	}
}

5.5、Switch的使用

1、通常情况下,path和component是一一对应的关系;
2、Switch可以提高路由匹配效率(单一匹配);

import React, { Component } from 'react'
import {Route,Switch} from 'react-router-dom'
import Home from './pages/Home' //Home是路由组件
import About from './pages/About' //About是路由组件
import Header from './components/Header' //Header是一般组件
import MyNavLink from './components/MyNavLink'
import Test from './pages/Test'

export default class App extends Component {
	render() {
		return (
			<div>
				<div className="row">
					<div className="col-xs-2 col-xs-offset-2">
						<div className="list-group">
							{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
							<MyNavLink to="/about">About</MyNavLink>
							<MyNavLink to="/home">Home</MyNavLink>
						</div>
					</div>
					<div className="col-xs-6">
						<div className="panel">
							<div className="panel-body">
								{/* Switch包裹时,路由匹配到路径时直接加载对应的组件;
								    Switch未包裹时,路由会一直向下匹配。如有相同的路径,不同的组件,加载最下面的组件*/}
								{/* 注册路由 */}
								<Switch>
									<Route path="/about" component={About}/>
									<Route path="/home" component={Home}/>
									<Route path="/home" component={Test}/>
								</Switch>
							</div>
						</div>
					</div>
				</div>
			</div>
		)
	}
}

5.6、多级路径刷新页面样式丢失问题

路由多级路径切换跳转后,点击浏览器刷新出现样式丢失问题。

...
// 路由多级路径/atguigu/about
<MyNavLink to="/atguigu/about">About</MyNavLink>
<MyNavLink to="/atguigu/home">Home</MyNavLink>

...

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

...

原因:在public/index.html中加载样式路径出现问题

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>react脚手架</title>
		<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
		<!-- 
		<link rel="stylesheet" href="./css/bootstrap.css">
	
		前端本地服务http://localhost:3000默认加载的是public下的内容;
		正常请求样式路径:http://localhost:3000/css/bootstrap.css
		多级路由刷新路径:http://localhost:3000/atguigu/css/bootstrap.css
		当请求发送不存在的路径时,返回public下的index.html中的内容
		-->
		<link rel="stylesheet" href="./css/bootstrap.css">
		<style>
			.atguigu{
				background-color: rgb(209, 137, 4) !important;
				color: white !important;
			}
		</style>
	</head>
	<body>
		<div id="root"></div>
	</body>
</html>

解决方案:
1、public/index.html中引入样式时不写.// (常用);
2、public/index.html中引入样式时不写./%PUBLIC_URL% (常用);
3、public/index.html中引入样式时写./,但是使用HashRouter代替BrowserRouter包裹App组件;

5.7、路由的严格匹配与模糊匹配

默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
开启严格匹配:<Route exact={true} path="/about" component={About}/>
注意:严格匹配不要随便开启,需要再开。有些时候开启会导致无法继续匹配二级路由

<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home/a/b">Home</MyNavLink>

......

<Switch>
	// 开启严格模式
	<Route exact path="/about" component={About}/>
	<Route exact path="/home" component={Home}/>
</Switch>

5.8、Redirect的使用

一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由

import {Route,Switch,Redirect} from 'react-router-dom'
......
<Switch>
	<Route path="/about" component={About}/>
	<Route path="/home" component={Home}/>
	<Redirect to="/about"/>
</Switch>

5.9、嵌套路由

注册子路由时要写上父路由的path值,路由的匹配是按照注册路由的顺序进行的

Home组件下的NewsMessage组件

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>
			)
	}
}

5.10、向路由组件传递参数

params传参
使用方式:
1、路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
2、注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
3、接收参数:this.props.match.params

search传参(query传参)
使用方式:
1、路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
2、注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
3、接收参数:this.props.location.search
备注:获取到的searchurlencoded编码字符串,需要借助querystring解析

state传参
使用方式:
1、路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
2、注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
3、接收参数:this.props.location.state
备注:刷新也可以保留住参数

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>
		)
	}
}

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

const DetailData = [
	{id:'01',content:'你好,中国'},
	{id:'02',content:'你好,尚硅谷'},
	{id:'03',content:'你好,未来的自己'}
]
export default class Detail extends Component {
	render() {
		console.log(this.props);
		{/* 第三步:props中读取参数 */}
		
		// 接收params参数
		// match: {..., params: {id: "01", title: "消息1"}}
		// const {id,title} = this.props.match.params 

		// 接收search参数
		// location: {..., search: "?id=01&title=消息1"}
		// const {search} = this.props.location
		// const {id,title} = qs.parse(search.slice(1))

		// 接收state参数
		// location: {..., state: {id: "01", title: "消息1"}}
		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>
		)
	}
}

5.11、路由组件与一般组件

1、写法不同:
一般组件:<Demo/>
路由组件:<Route path="/demo" component={Demo}/>

2、存放位置不同:
一般组件:components文件夹
路由组件:pages文件夹

3、接收到的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"

4、编程式路由导航
借助this.prosp.history对象上的API对操作路由跳转、前进、后退

  • this.prosp.history.push()
  • this.prosp.history.replace()
  • this.prosp.history.goBack()
  • this.prosp.history.goForward()
  • this.prosp.history.go()

5.12、withRouter使用

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)

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

5.13、BrowserRouter与HashRouter的区别

1、底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本;
HashRouter使用的是URL的哈希值;

2、path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test;
HashRouter的路径包含#,例如:localhost:3000/#/demo/test;

3、刷新后对路由state参数的影响
BrowserRouter没有任何影响,因为state保存在history对象中;
HashRouter刷新后会导致路由state参数的丢失;

4、HashRouter可以用于解决一些路径错误相关的问题;

6、第三方组件库

6.1、React UI组件库

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

ant-design(国内蚂蚁金服)
官网:https://ant.design/index-cn
Github:https://github.com/ant-design/ant-design/

6.2、antd的按需引入+自定主题

1、安装依赖:yarn add react-app-rewired customize-cra babel-plugin-import less less-loader
2、修改package.json

"scripts": {
	"start": "react-app-rewired start",
	"build": "react-app-rewired build",
	"test": "react-app-rewired test",
	"eject": "react-scripts eject"
},

3、根目录下创建config-overrides.js

// 配置具体的修改规则
const { override, fixBabelImports,addLessLoader} = require('customize-cra');
module.exports = override(
	fixBabelImports('import', {
		libraryName: 'antd',
		libraryDirectory: 'es',
		style: true,
	}),
	addLessLoader({
		lessOptions:{
			javascriptEnabled: true,
			modifyVars: { '@primary-color': 'green' },
		}
	}),
);

4、不用在组件里亲自引入样式了,即:import 'antd/dist/antd.css’应该删掉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/191703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

加速企业数字化进展,小程序容器来帮忙

近年来&#xff0c;由于新冠疫情&#xff0c;诸多企业面临经济挑战&#xff0c;高效办公常常无法正常保证。在此期间&#xff0c;不少企业纷纷加快了数字化进展。 2021年&#xff0c;在Gartner新型技术成熟度曲线中我们看到&#xff1a;组装式应用、实时事件中心即服务、生成式…

软考高级系统架构师背诵要点---系统安全与系统可靠性分析

系统安全与系统可靠性分析 系统安全&#xff1a; 信息摘要、数字签名、数字信封 被动攻击&#xff1a;收集信息为主&#xff0c;破坏保密性 窃听&#xff1a;用各种可能的合法手段和非法手段窃取系统中的信息资源和敏感信 业务流分析&#xff1a;通过对系统进行长期的监听&a…

Spark08: Spark Job的三种提交模式

一、三种任务提交方式 1. 第一种&#xff0c;standalone模式 基于Spark自己的standalone集群。指定–master spark://bigdata01:7077 2. 第二种&#xff0c;是基于YARN的client模式。 指定–master yarn --deploy-mode client 使用场景&#xff1a;这种方式主要用于测试&am…

Homekit智能家居DIY-智能通断开关

智能通断器&#xff0c;也叫开关模块&#xff0c;可以非常方便地接入家中原有开关、插座、灯具、电器的线路中&#xff0c;通过手机App或者语音即可控制电路通断&#xff0c;轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及&#xff0c;越来越多的人想将自己的家改…

自定义archetype脚手架完整步骤与异常情况处理方案

自定义archetype脚手架完整步骤与异常情况处理方案一、创建模板项目二、生成骨架jar包三、骨架安装到本地仓库如果出现安装位置错误的情况&#xff0c;参考以下场景处理&#xff1a;四、选择骨架&#xff0c;创建新项目创建项目时&#xff0c;如果一直卡在Generating project i…

Java集合(七)LinkedHashSet

LinkedHashSet的全面说明&#xff1a; &#xff08;1&#xff09;LinkedHashSet是HashSet的子类 &#xff08;2&#xff09;LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组双向链表 HashSet为数组单向链表 &#xff08;3&#xff09;LinkedHashSet根据元素的has…

Redis基础篇:Redis常见命令与数据结构

文章整理自B站黑马视频课程第一章&#xff1a;Redis数据结构介绍一&#xff1a;五种常见基本类型二&#xff1a;三种不常见类型第二章&#xff1a;数据类型的使用一&#xff1a;Redis通用命令二&#xff1a;String类型1&#xff1a;String常见命令2&#xff1a;String常见命令实…

任务系统的程序设计

任务是程序应用中常见的系统&#xff0c;它有助于用户代入角色&#xff0c;也有助于研发、运营和用户的互动&#xff0c;通常完成任务之后会给予用户一定的奖励。1&#xff0c;基本数据结构早期的任务系统设计的都很简单&#xff0c;大部分都是线性结构&#xff0c;偶尔会有环任…

负载均衡-

常见的负载均衡系统包括 3 种&#xff1a;DNS 负载均衡、硬件负载均衡和软件负载均衡。 DNS 负载均衡 DNS 是最简单也是最常见的负载均衡方式&#xff0c;一般用来实现地理级别的均衡。例如&#xff0c;北方的用户访问北京的机房&#xff0c;南方的用户访问深圳的机房。DNS 负…

【FreeRTOS】详细讲解FreeRTOS中事件(event)并通过具体示例讲述其用法

文章目录事件函数解析示例事件 事件&#xff0c;实际上是一种任务间通信的机制&#xff0c;主要用于实现多任务间的同步&#xff0c;其只能是事件类型的通信&#xff0c;无数据传输。与信号量不同的是&#xff0c;它可以实现一对多&#xff0c;多对多的同步。即可以是任意一个事…

为什么data属性是一个函数而不是一个对象?

一、实例和组件定义data的区别 vue实例的时候定义data属性既可以是一个对象&#xff0c;也可以是一个函数 const app new Vue({el:"#app",// 对象格式data:{foo:"foo"},// 函数格式data(){return {foo:"foo"}} }) 组件中定义data属性&#x…

MACD二次金叉选股公式,零轴上下、一次三次金叉举一反三

本文介绍了MACD二次金叉选股公式编写思路&#xff0c;以MACD零轴之下二次金叉为例&#xff0c;编写选股公式&#xff0c;进行信号过滤&#xff0c;并把选股公式改编为技术指标。此外举一反三&#xff0c;介绍了三次金叉以及MACD零轴上二次金叉。 一、MACD二次金叉选股公式编写 …

ECharts线性渐变色示例演示

第003个点击查看专栏目录Echarts的渐变色采用了echarts.graphic.LinearGradient的方法&#xff0c;可以根据代码中的内容来看如何使用。线性渐变&#xff0c;多用于折线柱形图&#xff0c;前四个参数分别是 x0, y0, x2, y2, 范围从 0 - 1&#xff0c;相当于在图形包围盒中的百分…

计算机图形学 第10章 真实感图形

目录 学习目标 前情提要 # RGB颜色模型 HSV颜色模型 CMYK颜色模型/印刷颜色模型 简单光照模型&#xff08;考&#xff09;⭐⭐⭐ 简单光照模型假定&#xff1a; 材质属性 环境光模型 漫反射光模型 镜面反射光模型 Phong反射模型: 光强衰减 增加颜色 光滑着色 直线段的…

CentOS 7.9安装zabbix6.0LTS版本

环境说明 这里使用为 CentOS 7.9版本进行测试验证&#xff0c;zabbix Server 采用源码包部署&#xff0c;数据库采用 MySQL8.0版本&#xff0c;zabbix-web使用 &#xff0c;nginxphp来实现。 具体信息如下&#xff1a; 软件名版本zabbix-server6.0.12LTSzabbix-agent6.0.12LT…

MySQL数据库的常见考点

文章目录1、ACID事务原理事务持久性事务原子性MVCC基本概念MVCC基本原理undo logundo log版本链readviewMVCC实现原理RC读已提交RR可重复读MVCC实现原理总结2、并发事务引发的问题3、事务隔离级别4、索引4.1、索引概述4.2、索引优缺点4.3、索引结构二叉树B-Tree树BTree树BTree优…

测试组合生成器-allpairspy

1、前言 在我们写功能用例时&#xff0c;常常会遇到多个参数有很多的选项&#xff0c;而如果想把这些参数值都要覆盖执行的话&#xff0c;工作量可想而知。那有没有什么办法既可以减少用例数量&#xff0c;也可以保证用例质量又降低测试时间成本&#xff0c;本篇将介绍一款工具…

关于机房精密空调监控系统,你想了解的都在这里!

机房精密空调是针对现代电子设备机房规划的专用空调&#xff0c;它的作业精度和可靠性都要比一般空调高得多。在计算机机房中的设备是由很多的微电子、精细 机械设备等组成&#xff0c;而这些设备运用了很多的易受温度、湿度影响的电子元器件、机械构件及资料&#xff0c;所以精…

Unreal学习笔记2-绘制简单三角形

文章目录1. 概述2. 详论2.1. 代码实现2.2. 解析&#xff1a;Component2.3. 解析&#xff1a;材质2.4. 解析&#xff1a;包围盒2.5. 解析&#xff1a;Section3. 其他4. 参考1. 概述 之所以写这个绘制简单三角形的实例其实是想知道如何在Unreal中通过代码绘制自定义Mesh&#xf…

网页开发:MySQL和Python案例

目录 一、MySQL的概念和引入 二、MySQL指令 1、数据库管理&#xff08;文件夹&#xff09; 2、数据表的管理&#xff08;文件&#xff09; 3、数据行操作 三、常用的数据类型 四、员工管理案例 1、使用MySQL内置工具&#xff08;命令&#xff09; 2、Python代码实现 ①…