目录
5.6 createContext、useContext 跨组件传值
一、JSX
jsx就是在js中输写html代码并渲染到页面
function App () {
return (
<div className="App">
react
</div>
)
}
二、函数组件和类组件
1.函数组件
函数组件在16.8版本之前被称为无状态组件,16.8版本之后加入了hooks之后被称为有状态组件
- 组件的名称必须首字母大写,react内部会根据这个来判断是组件还是普通的HTML标签
- 函数组件必须有返回值,表示该组件的 UI 结构;如果不需要渲染任何内容,则返回 null
- 组件就像 HTML 标签一样可以被渲染到页面中。组件表示的是一段结构内容,对于函数组件来说,渲染的内容是函数的返回值就是对应的内容
- 使用函数名称作为组件标签名称,可以成对出现也可以自闭合
function App () {
return (
<div className="App">
这是一个函数组件
</div>
)
}
2.类组件
- 类名称也必须以大写字母开头
- 类组件应该继承 React.Component 父类,从而使用父类中提供的方法或属性
- 类组件必须提供 render 方法render 方法必须有返回值,表示该组件的 UI 结构
import React from "react"
class App extends React.Component {
render () {
return (
<div>这是一个类组件</div>
)
}
}
3.js表达式
3.1函数组件
const Home = () => {
let name = "这是一个函数组件"
return (
<div>{name}</div>
)
}
3.2类组件
class App extends React.Component {
render () {
let name = "这是一个类组件"
return (
<><div>{name}</div><Home></Home></>
)
}
}
4.列表渲染
4.1函数组件
const list = [
{
id: 1,
name: '张三'
},
{
id: 2,
name: '李四'
}
]
const Home = () => {
return (
<div>
{list.map(item => <div key={item.id}>{item.name}</div>)}
</div>
)
}
export default Home
4.2类组件
import React from 'react'
const list = [
{
id: 1,
name: '张三'
},
{
id: 2,
name: '李四'
}
]
class Class extends React.Component {
render () {
return (
<>
{list.map(item => <div key={item.id}>{item.name}</div>)}
</>
)
}
}
export { Class }
5.条件渲染
<div>
{flag ? <div>flag等于true</div> : <div>flag等于false</div>}
</div>
6.样式处理
6.1行内样式
<div style={{ color: 'red' }}>红色的文字</div>
6.2行内样式优雅的写法
const color = {
color: 'red'
}
const Home = () => {
return (
<div>
<div style={color}>红色的文字</div>
</div>
)
}
export default Homej
6.3 className 外部引入
home.js
import './home.css' /* 2.导入样式文件 */
const Home = () => {
return (
<div>
{/* 1.定义类名 */}
<div className="words">红色的文字</div>
</div>
)
}
export default Home
home.css
.words{
color: red;
}
7.className与条件判断结合使用
import './home.css' /* 2.导入样式文件 */
const flag = false
const Home = () => {
return (
<div>
{/* 1.定义类名 */}
<div className={flag ? 'red' : 'yellow'}>红色的文字</div>
</div>
)
}
export default Home
三、进阶
1.事件处理
1.1类组件
import React from 'react'
/* 1.定义事件 */
const Click = () => {
console.log("事件处理")
}
class Class extends React.Component {
render () {
return (
<>
{/* 2.使用事件 */}
<button onClick={Click}>点击事件</button>
</>
)
}
}
export { Class }
1.2函数组件
const Click = () => {
console.log("函数组件点击事件")
}
const Home = () => {
return (
<div>
{/* 1.定义类名 */}
<button onClick={Click}>函数组件点击事件</button>
</div>
)
}
1.3 类组件状态
/* 定义状态 */
state = {
age: 10
}
1.4 事件更新(修改状态)
import React from 'react'
class Class extends React.Component {
/* 定义状态 */
state = {
age: 10
}
Click = () => {
this.setState({
age: this.state.age + 1
})
}
render () {
return (
<>
<div>我今年{this.state.age}岁了
<button onClick={this.Click}>年龄+1</button>
</div>
</>
)
}
}
export { Class }
1.5 事件传参
1.5.1类组件
import React from 'react'
class Class extends React.Component {
/* 定义状态 */
state = {
age: 10
}
Click = (e, i) => {
console.log(e, i)
}
render () {
return (
<>
<div>我今年{this.state.age}岁了
<button onClick={(e) => this.Click(e, this.state.age)}>年龄+1</button>
</div>
</>
)
}
}
export { Class }
1.5.2函数组件
const Home = () => {
const Click = (e) => {
console.log("函数组件点击事件")
console.log(e)
}
return (
<div>
<button onClick={(e) => Click(e)}>函数组件传参</button>
</div>
)
}
export default Home
2.类组件表单事件处理
class Class extends React.Component {
state = {
value: 10
}
change = (e) => {
/* 3.发生改变更改value值 */
this.setState({
value: e.target.value
})
}
render () {
return (
<>
<div>我今年{this.state.value}岁了
{/* 1. 先绑定数据 value={this.state.value} */}
{/* 2. onChange监听 */}
<input type="text" value={this.state.value} onChange={this.change} />
</div>
</>
)
}
}
export { Class }
3.组件通信
3.1父向子传值
3.1.1 props是只读对象(readonly)
根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改
3.1.2 props可以传递任意数据
数字、字符串、布尔值、数组、对象、函数、JSX
父组件传值
import { Name } from './name'
class Class extends React.Component {
state = {
value: "我是父向子传递的值"
}
render () {
return (
<>
<Name value={this.state.value}></Name>
</>
)
}
}
类子组件接收
class Name extends React.Component {
render () {
return (
<>
{this.props.value}
</>
)
}
}
函数子组件接收
const Hanshu = (props) => {
return (
<div>
{props.value}
</div>
)
}
export { Hanshu }
其实这里可以换一种更优美的写法。解构赋值
const Hanshu = ({ value }) => {
return (
<div>
{value}
</div>
)
}
3.2子向父传值
1.父组件先定义一个回调函数来接收参数
class Class extends React.Component {
state = {
value: "",
}
/* 1.定义一个回调函数来接收参数 */
name = (i) => {
this.setState({
value: i
})
}
render () {
return (
<>
<div>{this.state.value}</div>
{/* 2.将name回调函数发送到子组件 */}
<Hanshu name={this.name}></Hanshu>
</>
)
}
}
const Hanshu = ({ name }) => {
const value = "子向父传值过去了"
return (
<div>
{/* 点击传值 */}
<button onClick={() => name(value)}>子向父传值</button>
</div>
)
}
3.3兄弟组件传值
先子向父传,在父向子传,就完成了兄弟之间的传值
4.生命周期
注:生命周期只存在类组件
4.1挂在阶段案例
class App extends React.Component {
constructor() {
super()
console.log("constructor")
}
componentDidMount () {
console.log("componentDidMount")
}
render () {
console.log("render")
return (
<div>asd</div>
)
}
}
4.2 componentDidMount实战
componentDidMount () {
axios({
url: 'http://yufei.shop:3000/CommodityClassification'
}).then(res => {
console.log(res.data)
})
}
4.3 componentDidUpdate实战
class App extends React.Component {
state = { /* 1.定义数据 */
value: 0
}
/* 每点击一次render重新渲染ui componentDidUpdate将会更新一次 */
componentDidUpdate () {
console.log("componentDidUpdate", this.state.value, "被更新了")
}
/* 2.定义点击事件 */
flag = () => {
this.setState({
value: this.state.value + 1
})
}
render () {
console.log("render")
return (
<div>
<div>{this.state.value}</div>
<button onClick={this.flag}>+1</button>
</div>
)
}
4.4 componentWillUnmount实战
点击切换home组件,来实现组件被卸载的效果
import { Home } from "./home"
class App extends React.Component {
state = {
flag: true
}
gaibian = () => {
this.setState({
flag: !this.state.flag
})
}
render () {
return (
<div>
{this.state.flag ? <Home></Home> : null}
<button onClick={this.gaibian}>切换</button>
</div>
)
}
}
class Home extends React.Component {
constructor() {
super()
console.log("我又重生了")
}
componentWillUnmount () {
console.log("Home组件被卸载了")
}
render () {
return (
<div>Home</div>
)
}
}
export { Home }
5.Hooks
概念:一个能让函数组件强大的钩子。
16.8版本之前函数组件被称为无状态组件,16.8之后函数组件被称有有状态组件,这其中少不了hooks的功劳。
5.1 hooks解决了如下两个问题
- 组件的逻辑复用
在hooks出现之前,react先后尝试了 mixins混入,HOC高阶组件,render-props等模式
但是都有各自的问题,比如mixin的数据来源不清晰,高阶组件的嵌套问题等等 - class组件自身的问题
class组件就像一个厚重的‘战舰’ 一样,大而全,提供了很多东西,有不可忽视的学习成本,比如各种生命周期,this指向问题等等,而我们更多时候需要的是一个轻快灵活的'快艇'
5.1 useState 基本使用
useState:数据管理
import { useState } from 'react' /* 1.导入useState */
const App = () => {
/* 调用函数并附初始值
第一个参数为状态值
第二个参数为修改状态值 */
const [count, setCount] = useState(0)
return (
<div>
<div>{count}</div>
<button onClick={() => { setCount(count + 1) }}>+1</button>
</div>
)
}
export default App
5.2 useEffect
useEffect 就是为react函数组件提供副作用处理的!
什么是副作用
副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
可能不容易理解,比如说你在里面可以发送axios请求或者操作dom、或者本地存储等等操作
案例1 操作dom:
import { useState, useEffect } from 'react' /* 1.导入useState,useEffect */
const App = () => {
const [count, setCount] = useState(0)
useEffect(() => {
document.title = `当前点击了${count}次`
})
return (
<div>
<div>{count}</div>
<button onClick={() => { setCount(count + 1) }}>+1</button>
</div>
)
}
export default App
案例2 useEffect 会自动发起请求
const Axios_to = () => {
axios({
url: 'http://yufei.shop:3000/CommodityClassification'
}).then(res => {
console.log(res)
})
}
useEffect(() => {
Axios_to()
})
5.3 return清理useEffect副作用
如果大家实在不明白什么叫副作用你可以看作是生命周期
useEffect是创建后执行
清理useEffect副作用即可理解为组件卸载后执行的生命周期函数
import { useState } from 'react'
import { Home } from './Home'
function App() {
const [count, setCount] = useState(true)
return (
<div className="App">
{count ? <Home></Home> : null}
<button
onClick={() => {
setCount(!count)
}}>
显示隐藏
</button>
</div>
)
}
export default App
import { useEffect } from 'react'
const Home = () => {
useEffect(() => {
const dsq = setInterval(() => {
console.log('useEffect执行啦')
}, 1000)
return () => {
clearInterval(dsq)
console.log('组件卸载定时器清楚')
}
})
return <div>Home</div>
}
export { Home }
5.4useState 计算
提一个需求,当App组件传递过来值,Home组件拿到值后通过计算才能得到一个新的值。
const [age, useage] = useState(()=>{
return 1+2
})
5.5 useEffect监听
const Home = () => {
const [age, useage] = useState(0)
useEffect(() => {
console.log(age, 'age改变了')
}, [age]) /* 后面加上[age]条件,就会监听这个值 */
return (
<div>
<div>{age}</div>
<button onClick={() => useage(age + 1)}>+1</button>
</div>
)
}
5.6 useRef 获取dom
作用:获取dom
import { useRef, useEffect } from 'react'
const Home = () => {
const title = useRef(null) /* 定义useRef */
useEffect(() => {
console.log(title.current) /* title.current 获取这个dom */
title.current.style.color = 'red' /* 操作dom 让其颜色一开始就变为红色 */
}, [])
return (
<div>
<div ref={title}>useRef</div> {/* 绑定useRef */}
</div>
)
}
export { Home }
5.6 createContext、useContext 跨组件传值
作用:跨组件传值
import {
createContext,
useContext,
} from 'react' /* 1.获取 useContext*/
const Context = createContext() /* 2.创建Context对象 */
const Home = () => {
return (
<Context.Provider value={'this is home'}> {/* 传值 */}
<div>
Home
<Home2></Home2>
</div>
</Context.Provider>
)
}
const Home2 = () => {
return (
<div>
Home2
<Home3></Home3>
</div>
)
}
const Home3 = () => {
/* 底层接收组件 */
const name = useContext(Context) /* 通过 useContext(Context) 来进行接收*/
return <div>{name}</div>
}
export { Home }
6.Router路由
6.1 React下载
pnpm
pnpm add react-router-dom@6
npm
npm i react-router-dom@6
yarn
yarn add react-router-dom@6
6.2 核心内置组件说明
1. BrowserRouter 作用: 包裹整个应用,一个React应用只需要使用一次 h5的 history.pushState API实现
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/age" element={<Age />}></Route>
</Routes>
</BrowserRouter>
2.Link 你想去那里 作用: 用于指定导航链接,完成声明式的路由跳转 类似于 <router-link/>
<Link to="/age">跳转到age页面</Link>
3.Routes 作用: 提供一个路由出口,组件内部会存在多个内置的Route组件,满足条件的路由会被渲染到组件内部类比 router-view
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/age" element={<Age />}></Route>
</Routes>
4.Route 作用: 用于定义路由路径和渲染组件的对应关系 [element:因为react体系内 把组件叫做react element]
<Route path="/" element={<Home />}></Route>
// path:组件路径 element:组件
6.3 编程式导航
import { useNavigate } from 'react-router-dom' /* 导入useNavigate */
const Home = () => {
// 执行函数
const navigate = useNavigate()
return (
<div>
<button onClick={() => navigate('/age')}>编程式导航</button>
</div>
)
}
export { Home }
6.4 路由传参
1. searchParams传参
传
import { useNavigate } from 'react-router-dom' /* 导入useNavigate */
const Home = () => {
// 执行函数
const navigate = useNavigate()
const name = '张三爱喝酒'
return (
<div>
<button onClick={() => navigate(`/age?name=${name}`)}>编程式导航</button>
</div>
)
}
export { Home }
接收
import { useSearchParams } from 'react-router-dom'
const Age = () => {
let [params] = useSearchParams()
let name = params.get('name')
return <div>{name}</div>
}
export { Age }