前言:用过class之后,很长一段时间没有接触过react了。现在从头复习一遍基操。
React 从16.8之后出现了一个新的hook,个人理解是函数+api。
个人建议先熟悉一遍官方文档。
好了,废话不多说。整起来!
一. 使用react脚手架创建项目:
1.全局安装:npm i -g create-react-app
2.切换到想创建项目的目录,使用命令 create-react-app demo(项目名称) 【mac电脑前面加sudo】
3.进入项目文件夹 cd demo
4.启动项目 npm start || yarn start(推荐安装yarn,都是Facebook公司开发的)
刚开始启动应该是这样的
二.项目文件说明:
再运行 npm run eject 暴露配置文件。文件会变多,可自行配置。
react 关闭严格模式,根目录下 index.js 中注释掉 <React.StrictMode> 标签
// index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// <React.StrictMode>
<App />
// </React.StrictMode>
);
三. 引入第三方组件库 antDesign
npm install antd --save
1.1. 在src/App.css,文件顶部引入@import '~antd/dist/antd.css';
。- 高级配置
2.安装 craco yarn add @craco/craco
解决报错 忽略版本问题 yarn config set ignore-engines true
修改 package.json 里的 scripts 属性。
/* 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.1 首先把 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';
2.2 安装 craco-less yarn add craco-less
修改 craco.config.js 文件如下。
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: { '@primary-color': '#1DA57A' },
javascriptEnabled: true,
},
},
},
},
],
};
- 组件中使用直接引入组件,无需引入额外样式文件:
import { Button } from 'antd';
三. hook的基本用法。
在react16.8 版本以前我们用的都是class 组件
import React, { Component } from 'react'
export default class Home extends Component {
render() {
return (
<h3>我是Home的内容</h3>
)
}
}
使用hook,Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
1. ,使用 useState和useEffect,创建文件 components/Test1/test1.jsx
import React,{useState,useEffect} from "react";
const useTest1=()=>{
// count 声明变量,setCount 设置变量,useState 为默认值
const [count,setCount]=useState(0);
// 相当于 componentDidMount 和 componentDidUpdate:
useEffect(() => {
// 使用浏览器的 API 更新页面标题
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>数字:{count}</p>
<Button type="primary" onClick={()=>setCount(count+1)}>点击这里++</Button>
</div>
)
}
export default useTest1;
2. App.js中引入:
import './App.css';
import Test1 from './components/Test1/test1'
function App() {
return (
<div>
<Test1></Test1>
</div>
)
}
export default App;
页面效果:
四. 基本路由:
1. 安装依赖 npm install react-router-dom
2. components/Header/header文件内容
import React from 'react';
function Header(param) {
return <h1>Hello {param.name}!</h1>;
}
export default Header;
3. 在App.js中使用:
import './App.css';
import {BrowserRouter,Link,Route, Routes} from 'react-router-dom'; //引入路由组件
import Header from './components/Header/header' //这里自定义组件的 Path
import Test1 from './components/Test1/test1' //这里自定义组件的 Path
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/header' element={<Header />} />
<Route path='/test1' element={<Test1 />} />
</Routes>
<div>
<div>
<Link to="/header" >
<h1 >Header</h1>
</Link>
<Link to="/test1">
<h2 >Test1</h2>
</Link>
</div>
</div>
</BrowserRouter>
</div>
)
}
export default App;
效果图:
4.路由页面跳转
// App.js 中注册路由页面
import './App.css';
import {BrowserRouter,Link,Route, Routes} from 'react-router-dom';
import Test1 from './components/Test1/test1' //这里自定义组件的 Path
import Test2 from './components/Test1/test2' //这里自定义组件的 Path
import Test3 from './components/Test1/test3' //这里自定义组件的 Path
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/test1' element={<Test1 />} />
<Route path='/test2' element={<Test2 />} />
<Route path='/test3' element={<Test3 />} />
</Routes>
<div>
<div>
<Link to="/test1">
<h2 >Test1 页面</h2>
</Link>
</div>
</div>
</BrowserRouter>
</div>
)
}
export default App;
4.1 使用标签 Link to 进行跳转,useLocation 接受参数
新建test2和test3组件
// test2.jsx 进行跳转传参
import React from 'react';
import {Link} from 'react-router-dom';
const Test2= () =>{
return(
<div>
test2
<Link to={`/test3`} state={{ data: "the-page-id" }}>点击跳转到test3</Link>
</div>
)
}
export default Test2
// test3.jsx useLocation 参数接受
import React, { useState,useCallback } from 'react';
import {useLocation,Link} from 'react-router-dom';
const Test3= () =>{
const data=useLocation()
console.log(data.state)
return(
<div>
test3
<Link to={`/test2`} state={{ data: "the-page-id" }}>点击跳转到test2</Link>
</div>
)
}
export default Test3
4.2 点击跳转:引入 import {useNavigate} from 'react-router-dom';
// test2.jsx 点击跳转
import React from 'react';
import {useNavigate} from 'react-router-dom';
const Test2= () =>{
const navigate = useNavigate();
function target(){
navigate("/test3",{ state: 'response.data.data' })
}
return(
<div>
test2
<button onClick={()=>target()}>点击跳转到test3</button>
</div>
)
}
export default Test2
// test3.jsx 进行接受
import React, { useState,useCallback } from 'react';
import {useLocation,Link} from 'react-router-dom';
const Test3= () =>{
const data=useLocation()
console.log(data)
return(
<div>
test3
<Link to={`/test2`} state={{ data: "the-page-id" }}>点击跳转到test2</Link>
</div>
)
}
export default Test3
五. 组件通信:
1.父传子,引入子组件直接添加属性传值。
// 父组件
import React, { useState,useCallback } from 'react';
import Child from '../Children/children';//子组件
const Test1= () =>{
const [count , setCount ] = useState(0)
return(
<div>
<div>
<p>父组件的值: {count} </p>
<Child value={count} />
</div>
</div>
)
}
export default Test1
// 子组件
import React, { useState,useEffect } from 'react';
const Child= (props) =>{
console.log('props',props);
return(
<div>
<h2>子组件接受的数值:{props.value}</h2>
</div>
)
}
export default Child
2.子传父:
// 父组件
import React, { useState,useCallback } from 'react';
import Child from '../Children/children';// 引入子组件
const Example= (props) =>{
const [count , setCount ] = useState(0)
const [childData, setChildData] = useState(); //获取子组件的值
const getchildfn = useCallback((data) => {
setChildData(data);
}, []);
return(
<div>
<div>
<p>父组件的值: {count} </p>
<button onClick={()=>{setCount(count+1)}}>父组件点击</button>
<h1>子组件的值: {childData}</h1>
<Child value={count} handleChildData={getchildfn}/>
</div>
</div>
)
}
export default Example
// 子组件
import React, { useState,useEffect } from 'react';
const Child= (props) =>{
console.log('props',props);
const [childtext , setchildtext ] = useState('子组件默认值')
useEffect(()=>{
props.handleChildData(childtext)
},[childtext])
return(
<div>
<h2>子组件接受的数值:{props.value}</h2>
<button onClick={()=>{ setchildtext('今天给爸爸洗脚')}}>子组件点击改变1</button>
<button onClick={()=>{ setchildtext('今天给老子洗脚')}}>子组件点击改变2</button>
</div>
)
}
export default Child
3.子孙兄弟传值,公共组件 createContext.js
// 父组件
import React, { useState } from 'react';
import Child from './child.js';//子组件
import myContextContext from './createContext' ; //公共组件
const Example= (props) =>{
const [count , setCount ] = useState(0)
return(
<div>
<div>
<p>you click {count} times</p>
<button onClick={()=>{setCount(count+1)}}>click me</button>
<myContextContext .Provider value ={count}>
<Child/>
</myContextContext .Provider>
</div>
</div>
)
}
export default Example
// 子组件
import React, { useContext } from 'react';
import myContextContext from './createContext';
const Child= () =>{
const count= useContext(myContextContext ); // 得到父组件传的值
return(<h2>{count}</h2>)
}
export default Child
// 公共组件 createContext.js
import { createContext } from "react";
const myContextContext = createContext(null);
export default myContextContext ;