购物车
- index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store/index'
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
- app.js
import React from 'react';
import Add from './add';
import List from "./list"
import Footer from "./footer"
function App() {
return (
<div className="App">
<h1>购物车</h1>
<Add />
<List />
<Footer></Footer>
</div>
);
}
export default App;
- add.js
import React,{useState} from "react";
import { useDispatch } from "react-redux";
function Add () {
let [name, setName] = useState("")
let [price, setPrice] = useState("")
let dispatch =useDispatch()
return (
<div>
添加商品:
<input
type="text"
placeholder="请输入商品名称"
value={name}
onChange={({ target }) => {//注意{target}
setName(target.value)
}}
></input>
<input
type="text"
placeholder="请输入商品价格"
value = {price}
onChange={({target})=>{
setPrice(parseFloat(target.value));
}}
/>
<button
onClick={() => {
dispatch({
type: 'add',
data: {
id: Date.now(),
name,
price,
number: 1
}
});
setName('')
setPrice('')
}}
>添加商品</button>
</div>
)
}
export default Add
- store
- index.js
import { createStore } from 'redux'
import reducer from './reducer'
export default createStore(reducer)
- reducer.js
export default function reducer(state=[
{
id: 0,
name: "苹果",
price: 7,
number: 1
},{
id: 1,
name: "栗子",
price: 16,
number: 2
}
],action){
// eslint-disable-next-line default-case
switch(action.type){
case "add":
state.push(action.data);
return [...state];
case "plus":
for(let i = 0; i<state.length; i++){
if(state[i].id === action.id){
++state[i].number;
return [...state];
}
}
// eslint-disable-next-line no-fallthrough
case "minus":
for(let i = 0; i<state.length; i++){
if(state[i].id === action.id){
(state[i].number>0)&&(--state[i].number);
return [...state];
}
}
}
return state;
}
- list.js
import React from "react";
import { useSelector } from "react-redux";
import Li from './Li'
function List () {
let data=useSelector(state=>state)
return (
<ul>
{data.map(item => (<Li key={item.id} data={item}></Li>))}
</ul>
)
}
export default List
- Li,js
import React from "react";
import {useDispatch} from "react-redux";
function Li (props) {
let { id, name, price, number } = props.data
let dispatch = useDispatch();
return (
<li>
{name}-{price}元/件-共<button
onClick={() => {
dispatch({
type: "minus",
id
})
}}
>-</button>{number}件<button
onClick={() => {
dispatch({
type: "plus",
id
})
}}
>+</button>-共{price * number}元
</li>
)
}
export default Li
- footer.js
import React from "react";
import { useSelector } from "react-redux";
function Footer () {//首字母一定要大写
let data = useSelector(state=>(state.filter(item=>item.number>0)));
let number = data.reduce((n1, n2)=> {
return n1+n2.number
},0)
let allPrice=data.reduce((n1, n2)=> {
return n1+n2.number*n2.price
}, 0)
let maxPrice=data.reduce((n1, n2)=> {
return Math.max(n1,n2.price)
},0)
return (
<footer>总计:{number}件商品;共计花费{allPrice}元,最贵单价为{maxPrice}元</footer>
)
}
export default Footer
CSS Modules
- 在 create-react-app 中的使用:
- .css .sass 正常文件
- [name].module.css [name].module.sass 需要模块化的文件,文件命名加上module
import React from 'react';
import "./reset.css";
import styleed from "./app.module.css";///引入
import Child from './child';
function App() {
return (
<div className={styleed.app}>//使用,会自动生成hash后缀,避免命名重复
<Child />
<div className="box"></div>
</div>
);
}
export default App;
- CSS Modules 使用
- 局部 声明:local(.className) .className 使用 styled.className
- 全局 :global(.className)
body {
margin: 0;
}
.app {
margin: 0 auto;
width: 800px;
min-height: 100px;
border: 1px solid #000;
}
:global(.box) {
width: 300px;
height: 300px;
border: 2px solid #000;
border-radius: 50%;
}
import React, { Fragment } from 'react';
import style from "./child.module.css";
/**
*
* box 全局通用
*/
function Child() {
return (
<Fragment>
<h1 id={style.title}>标题</h1>
<div className={style.app}>
<div></div>
</div>
<div className="box"></div>
<div className={style.app2}></div>
</Fragment>
);
}
export default Child;
Ant Design
官网: https://ant.design/index-cn
- 使用
- 最基本使用
- 安装 npm install antd
- 引入 import { DatePicker } from ‘antd’; ReactDOM.render(, mountNode); import
‘antd/dist/antd.css’;
- 在 create-react-app 中使用 antd 并模块化我们的样式
- npm i antd
- npm i react-app-rewired customize-cra react-app-rewired 自定义 create-react-app 的配置
- 修改 package.json
- “scripts”: {
“start”: “react-scripts start”,
“start”: “react-app-rewired start”,
“build”: “react-scripts build”,
“build”: “react-app-rewired build”,
“test”: “react-scripts test”,
“test”: “react-app-rewired test”, } - 安装 babel-plugin-import npm i babel-plugin-import babel-plugin-import 是一个用于按需加
载组件代码和样式的 babel 插件 - 在项目根目录创建一个 config-overrides.js 用于添加babel-plugin-import配置
用到什么组件,就打包什么组件的样式,不用全部样式引入
- 在项目中使用 less 语法
- 安装 npm i less less-loader
- 修改 config-overrides.js 配置
const { override, fixBabelImports, addLessLoader } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,///引入less之后修改
}),
addLessLoader({///引入less之后修改
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}),
);
import React from 'react';
import {Button} from "antd";
import "./index.less";
function App() {
return (
<div className="wrap">
<Button>这是一个按钮</Button>
</div>
);
}
export default App;
@w:100px;
.wrap {
width: @w;
height: @w;
background: #ccc;
}
搭建 CNode 案例
测试接口地址:https://cnodejs.org/api
antd样式导入配置
create-react-app 脚手架搭建的react项目不支持 less,配置less步骤:
方式1 使用 react-app-rewired 和 customize-cra 来自定义 create-react-app 的 webpack 配置。
步骤 ,见上个案例,遇到问题:
- npm i react-app-rewired安装不上,导致npm satrt启动不成功,转为使用yarn add react-app-rewired
方式2 使用 craco (一个对 create-react-app 进行自定义配置的社区解决方案)
- 1.现在我们安装 craco 并修改 package.json 里的 scripts 属性。
$ yarn add @craco/craco
/* package.json */
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
}
- 2.按照 配置主题 的要求,自定义主题需要用到类似 less-loader 提供的 less 变量覆盖功能。我们可以引入 craco-less 来帮助加载 less 样式和修改变量。
首先把 src/App.css 文件修改为 src/App.less,然后修改样式引用为 less 文件。
/* src/App.js */
- import './App.css';
+ import './App.less';
/* src/App.less */
- @import '~antd/dist/antd.css';
+ @import '~antd/dist/antd.less';
- 3.然后安装 craco-less
$ yarn add craco-less
- 4.修改 craco.config.js 文件如下。注意官网示例没有配置webpack的src路径,所以@import ‘~antd/dist/antd.less’;报错
在这里插入代码片
const CracoLessPlugin = require('craco-less');
const path = require("path");
module.exports = {
babel: {
plugins: [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "es",
"style": true// true 针对less
}
]
]
},
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: { '@primary-color': '#1DA57A' }, //主题色
javascriptEnabled: true,
},
},
},
},
],
//配置src路径
webpack: {
alias: {
"@": path.resolve("src"),
},
},
};
方式3 :使用 create-react-app 提供的 yarn run eject 命令将所有内建的配置暴露出来
参考文献:react+antd 项目使用.less以及引入babel-plugin-import实现按需加载
- 1、使用命令将配置文件暴露出来
yarn eject // 或者 npm run eject
- 2、安装 less,less-loader 插件
yarn add less less-loader
- 3.打开webpack.config.js文件
- 4.添加配置代码
添加less的部分
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
//less
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
},
'less-loader'
),
sideEffects: true,
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader'
),
},
遇到的问题
- antd组件的使用,最新版本和旧版本有所不同
- require