React 快速入门
react
JSX语法
几乎和html一样,有些属性名称不同
class => className
<div style={{ background: "red" }}> # 内嵌样式
return (
<ul>
{list.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
)
组件
函数组件(无状态组件)
约定1:函数名字必须大写字母开头
约定2:函数必须有返回值
返回null表示不渲染内容
类组件(有状态组件)
可以通过类属性(state)保存状态
约定1:类名必须大写字母开头
约定2:类组件必须继承React.Compont
约定3:类组件必须提供render(),返回值就是组件的jsx
import使用
如果组件是export default 导出,就不用{},一个模块中只能有一个默认导出export default
如果是具名导出 export user; 就需要{user},名字保持一致
import Home from './pages/Home'
import {user} from './pages/CityList'
import './index.scss' // 直接引入样式文件
事件处理
事件绑定
在jsx中,对元素标签绑定事件
语法:on+事件={事件处理程序}, 比如onClick = {handleClick}
事件对象
在事件处理程序中,可以设置第一个参数获取事件对象。react事件对象兼容所有的浏览器,不需要额外处理
function handleClick(e){e.preventDefault()}
OnClick函数传参
<button onClick={jumpToDeposit(item)}>Deposit</button> # 这样写,button渲染的时候就执行了jumpToDeposit(),点击的时候不会执行
<button onClick={(e)=>{jumpToDeposit(item)}}>Deposit</button> # 这样写才行,button渲染时得到闭包函数,函数里面执行jumpToDeposit()
组件的state
只有类组件有state,state是私有的,只有组件内部能使用,this.state获取当前主机的所有state数据。
修改state的值,setState()作用:1.修改state值,2.更新UI
this.setState({count:this.state.count+1})
//不能直接修改
this.state.count++ //错误
组件通信——props
传递数据:在组件标签添加属性
函数组件通过props参数实现组件数据接收,类组件通过this.props属性获取数据
props是只读对象,不能修改
props可以接受任意类型的数据
props.children属性特指组件标签包含的子节点
props可以设置默认值,
<Hello name="jack" age={19}>这是组件子节点</Hello>
func Hello(props) {
return (
<div>
接收到数据{props.name}
组件中的子节点{props.children}
组件的默认值{props.pageSize}
</div>
)
}
// 给组件添加默认值
Hello.defaultPros={
pageSize:10
}
父组件传递数据给子组件
父组件把传递的数据放在state中
给子组件添加属性,并且使用state赋值
子组件通过props获取数据
class Hello extends React.Component{
state = {
list:[]
}
render(){
return (<Child list={this.state.list} />)
}
}
子组件传递数据给父组件
父组件通过回调函数接收数据,父组件先把回调函数传递给子组件。
子组件通过props获取父回调函数
子组件调用父回调函数,并且传递数据即可。
class Hello extends React.Component{
receiveMsg =(data)=>{
console.log("接收到数据", data)
}
render(){
return (<Child receiveMsg={this.receiveMsg} />)
}
}
class Child extends React.Component{
state={
msg:"hello world"
}
handleClick = ()=>{
this.props.receiveMsg(this.state.msg)
}
render(){
return (<div onClick={this.handleClick}>发送数据给父组件</div>)
}
}
兄弟组件通信
状态提升:把需要传递的数据放在共同的父组件中
父组件把状态传递给读子组件
父组件把修改状态方法传递给写子组件
跨组件通信
Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。
组件的生命周期
只有类组件才有生命周期,每个阶段都有钩子函数,方便我们在不同时期做操作。
1.创建时(加载时),会执行三个函数
constructor() -> render() ->componentDidMount()
钩子函数 | 触发时机 | 一般使用 |
---|---|---|
constructor | 创建组件时 | 初始化state |
render() | 每次组件渲染时触发 | 渲染UI, 不能执行setState() |
componentDidMount() | 组件挂载(完成DOM渲染)后 | 1.发送网络请求 2.DOM操作 |
- 更新时
组件接收props, setState(), forceUpdate()执行这些操作时,会触发更新
render() -> componentDidUpdate()
钩子函数 | 触发时机 | 一般使用 |
---|---|---|
render() | 每次组件渲染时触发 | 渲染UI, 不能执行setState() |
componentDidMount() | 组件挂载(完成DOM渲染)后 | 1.发送网络请求 2.DOM操作 3.执行setState必须放在if条件中,不然会死循环 |
3.卸载时
componentWillUnmount(), 一般是执行清理工作,比如定时器
组件复用
比如复用state和操作state的方法
两种处理方法,
注意:这两种方式不是新API,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)
1.render props模式
调用组件时,从外面传入render逻辑,不同的render逻辑,就可以实现同一个组件,但是不同的展示。实现了state共用,但是ui渲染不同的写法。
2.高阶组件(HOC)
React原理
setState()的说明
这是异步函数,使用该语法,在setState()后面的代码注意state的值不会马上修改的。
setState()会执行两个步骤,1.修改state的值 2.更新render渲染, 可以多次执行setState(),但是ui只会触发一次重新渲染。
// 通过传入回调函数来更新state
this.setState((state,props)=>{
return {count: state.count+1}
})
// 想在状态更新后并且重新渲染后,立即执行逻辑,可以在setState第二个参数传入callback
this.setState(
(state,props)=>{},
()=>{
document.title="更新state后"
}
)
JSX语法的转化过程
JSX仅仅是createElement()方法的语法糖,JSX语法会被@babel/preset-react插件编译为createElement()方法。
createElement()方法返回一个React元素(一个js对象),描述页面展示的内容。
组件更新机制
父组件重新渲染时,也会重新渲染子组件。
组件性能优化
减轻state
只存储组件渲染相关的数据,可以放到this对象中。
避免不必要的重新渲染
shoudComponentUpdate(nextprops,nextState) //钩子函数,返回fasle表示组件不会重新渲染,可以对比this.state和nextState的值,判断有些情况是不用重新渲染的
虚拟DOM和Diff算法
React的state修改后,会重新渲染整个组件,实际在底层,只会修改变化的虚拟DOM(就是js对象,描述DOM的一些属性),虚拟DOM可以让React脱离浏览器环境,做到跨平台应用。
React路由
现代的前端大多数SPA(单页应用程序),为了有效的使用单个页面来管理原来多个页面的功能,前端路由应运而生。
前端路由功能:让用户从一个视图导航到另外一个视图。
前端路由是一套映射规则,在React中,URL路径与组件的对应关系
使用步骤
yarn add react-router-dom
导入路由的三个核心组件Router,Route,Link
import {BrowserRouter as Router, Routes, Route, Link} from 'react-router-dom'
使用Router包裹整个应用
<Router>
<Link to="/first">页面一 </Link>
<Link to="/second">页面二</Link>
<Routes>
<Route path="/first" element={<Page1/>} />
<Route path="/second" element={<Page2/>} />
</Routes>
</Router>
Link传参,通过useLocation读取参数
<Link to='/params' state={{id:1}} />
// 接受路由参数
import {useLocation} from 'react-router-dom'
function UseParams() {
const location = useLocation()
console.log(location.state.id)
return (
<div>UseParams</div>
)
}
export default UseParams
常用组件的说明
BrowserRouter: 包裹整个应用,一个React应用只需要使用一次。
Link组件:路由的入口,会被编译为一个a标签。
<Link to="/first" 页面一>
Route: 路由的出口,展示对应的组件的视图。
<Routes>
<Route path="/first" element={<Page1/>} />
</Routes>
路由的执行过程
- 点击Link会修改浏览器地址栏的url
- React路由监听浏览器的url
- React路由遍历所有的Route组件,使用路由规则(path)与pathname进行匹配
- 当路由规则能够找到对应的pathname是,就展示对应的Route组件的内容
编程式导航:
通过JS代码实现页面跳转
嵌套路由
页面中嵌套页面
layout页面是一级路由,about,content是二级路由
layout
about
content
创建一级路由页面Layout
import {Outlet} from 'react-router-dom'
function Layout() {
return (
<div>
Layout
<Outlet/> // 二级路由出口
</div>
)
}
export default Layout;
定义嵌套路由
// 1.定义嵌套路由
<Route path='/' element={<Layout />}>
<Route path='about' element={<About />} />
<Route path='content' element={<Content />} />
</Route>
默认二级路由
添加index属性,删除自己的path,这样访问/时,默认显示的二级路由是About
<Route path='/' element={<Layout />}>
<Route index element={<About />} />
<Route path='content' element={<Content />} />
</Route>
- 404路由
<Routes>
<Route path='/login' element={<Login/>} />
{/* 所有路由都没有匹配时,显示nofound组件 */}
<Route path='*' element={<NoFound />} />
</Routes>
编程式导航
在组件中进行路由跳转
// 1.import 跳转函数
import { useNavigate } from 'react-router-dom';
function Login() {
// 2. 获取跳转函数
const navigate = useNavigate()
function goAbout() {
// 3.执行跳转
navigate('/about')
}
return (
<div>
Login
<button onClick={goAbout}>跳转到about</button>
</div>
)
}
export default Login;
跳转传参数
1.searchParams传参
navigate(/about?id=1)
读取取参数
const [params] = useSearchParams() // 返回的是数组
let id = params.get('id')
2. 通过state传参
const jumpToDeposit = (item)=>{
navigate('/deposit', {state:{id:item.ID,
playA:item.PlayA,
playB:item.PlayB,
playAID:item.PlayAID,
startTime:item.StartTime,
contractAddr:item.ContractAddr
}})
}
读取参数
const location = useLocation()
console.log(location.state) // 读取到传递的对象
本作品采用《CC 协议》,转载必须注明作者和本文链接