React基础笔记2
一、生命周期函数
挂载卸载过程
constructor props context
componentWillMount 服务器与客户端
componentDidMount ajax请求
componentWillUnmount 清除动画
更新过程
componentwillRecieveUpdata(nextProps)
shouldComponentwillupdata(nextProps,nextState) 组件渲染监听
componentDidupdata()
componentWillupdata
render 更新组建
二、网络请求与反向代理
1、网络请求
下载: npm i -S axios
// 组件挂载完毕后,执行的方法 只执行一次 componentDidMount() { axios.get('http://localhost:3000/data/users.json') .then(ret => { console.log(ret); }) }
2、反向代理
下载:npm i -S http-proxy-middleware
新建:setupProxy.js
const {createProxyMiddleware: proxy} = require('http-proxy-middleware') module.exports = app => { app.use('/api', proxy({ target: 'http://localhost:8082', changeOrigin: true, pathRewrite: { '^/api': '' } })) }
三、高阶组件(HOC)
一个函数,传给它一个组件,它返回一个新的组件
- 首先创建一个高阶组件函数
- 指定函数参数,参数应该以大写字母开头
- 在函数内部创建一个类组件,提供复用的状态逻辑代码并返回
- 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
- 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面
1、普通写法
定义高阶组件
import React, { Component } from 'react'; // Fragment jsx不会解析为html,但是它能当作 顶级元素 相当于vue中的template // react提供一种简写 <></> // 高阶组件是一个函数且 参数 是一个首字母要大写的组件 function withCmp(Cmp) { // 需要一个类组件且此组件要有返回 return class HocCmp extends Component { // 渲染 render() { // let title = this.props.title+'----...' return ( <> <h1>头部</h1> { // 子组件 通过props传给参数组件 } <Cmp {...this.props}></Cmp> <h4>底部</h4> </> ) } } } export default withCmp
调用高阶组件
import React, { Component } from 'react' // Home组件增强一些功能,使用此组件就自带头和尾,但是有时候又可不没有 // 对于Home组件使用高阶组件进行包裹 import Home from './pages/Home' // 导入高阶组件 函数 import hocCmp from './hoc/withCmp' let Myhome = hocCmp(Home) export default class App extends Component { state = { title: '我是一个标题', desc: '描述' } render() { return ( <div> {/* 高阶组件 */} <Myhome state={this.state} /> <Home title={this.state.title} /> </div> ) } }
2、装饰器渲染
装饰器是一种函数,写成 @函数名
1、安装:npm i -D customize-cra react-app-rewired
2、修改package.json文件中scripts命令
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", }
3、创建config-overrides.js配置文件
// 环境是一个commonjs规范环境 const path = require('path') // customize-cra 把webpack配置定义成方法,方便使用调用,不用去写webpack配置 const { addDecoratorsLegacy, override } = require('customize-cra') // 自定义一些webpack配置 定义成函数 const customize = () => (config, env) => { config.resolve.alias['@'] = path.join(__dirname, 'src') return config } // 模块导出 override=> 把你现在的配置和react中的webpack配置合并,它优先级更高 module.exports = override( // 让webpack支持 decorator addDecoratorsLegacy(), customize() )
4、使用装饰器
不用的写法
装饰器写法
解决警告问题
我们解决这个警告 需要在根目录配置一个tsconfig.json 文件
{ "compilerOptions": { "experimentalDecorators": true, "allowJs": true } }
3、memoization(计算属性-记忆组件)
连续两次相同传参,第二次会直接返回上次的结果,每次传参不一样,就直接调用函数返回新的结果,会丢失之前的记录,并不是完全记忆,可以在它的参数中传入state数据从而实现了类似Vue中的计算属性功能
安装:npm i -S memoize-one
# 引入 import memoizeOne from 'memoize-one' # 使用 getValue = memoizeOne( (x,y) => x+y ) # 调用 render(){ let total = this.getValue(this.state.x, this.state.y) return <div>{total}</div> }
4、memo(自带)
React.memo()是一个高阶函数,它与 React.PureComponent类似,但是一个函数组件而非一个类
import React from 'react' export default React.memo( props => { console.log('child---render') return ( <div>{props.title}</div> ) } )
三、状态管理(redux)
项目组件的数量和层级也变得越来越多,越来越深,此时组件间的数据通信就变得异常的复杂和低效,为了解决这个问题,引入了状态管理(redux)从而很好的解决多组件之间的通信问题。
安装:npm i -S redux
三大原则
- 单一数据源 store
- State 是只读的
- 使用纯函数(reducer)来执行修改
import {createStore} from 'redux' // 数据源 const defaultStore={ name:'张珊' } // 不能直接修改state function reducers(state=defaultStore,action){ try { if(action.type=='incr'){ return { name:'sad'+state.name } } } catch (error) { return state } } // 创建仓库 const store=createStore( reducers, window._REDUX_DEVTOOLS_EXTENSION__&&window.__REDUX__DEVTOOLS_EXTENSION__() ) // 导出 export default store
app.jsx
import React, { Component } from 'react' import store from './index' export default class App extends Comment { constructor(props) { super(props) // 1、获取数据store this.state = store.getState() // 2、订阅,数据修改自己更新状态数据 store.subscribe(() => { this.setState(state => store.getState()) }) } render(){ return( <div> <h3>{this.state.name}</h3> <button onClick={this.incr}>名称</button> </div> ) } incr=()=>{ // 3、action creator 必须是对象 const actionCreator={ type:'incr', payload:1 } // 4、派发一个reducer任务 store.dispatch(actionCreator) } }
1、react-redux与redux-thunk
react-redux:edux给我们提供一些高阶组件
redux-thunk:redux异步操作
npm i -S redux react-redux redux-thunk
1)、全局共享store
index.js
import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import store from './store' import App from './App' ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
2)、定义方法 action
countAction.js
const incrAction = num => ({ type: 'incr', payload: num }) // 共有函数 export const incr = () => dispatch => { setTimeout(() => { let num = 10 dispatch(incrAction(num)) }, 2000); }
3)、app中调用方法 使用react-redux
app.jsx
import React,{Component} from 'react' import {connect}from 'react-redux' import * as actions from './store/actions/countAction' /* 装饰器 参数1:吧redux的state映射成props 参数2 mapPropsToDispath */ @connect(state=>(state),actions) export default class App extends Component{ render(){ return( <div> <h3>{this.props.count}</h3> shouye <button onClick={this.incr}></button> </div> ) } incr=()=>{ this.props.incr() } }
4)、入口记录相关内容
index.js
import {createStore,applyMiddleware,compose} from 'redux' import thunk from 'redux-thunk' import reducer from './reducers/countReducer' // 记录日志中间件 const mym=store=>next=>action=>{ console.log(action,store) next(action) } // 配置chrom的dedux const composeEnhancers=typeof window=='object' &&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose const engancer=composeEnhancers( applyMiddleware(thunk,mym) ) // 导出 export default createStore( reducer, engancer )
5)、定义数据源
countRedycer.js
import CountMethod from '../methods/CountMethod' const defaultState={ count:1 } export default (state=defaultState,action)=>{ try { return CountMethod[actions.type](state,action.payload) } catch (error) { return state } }
6)、整合数据返回对应的值
// 处理 class CountMethod{ incr(state,data){ return { count: state.count+data } } } export default new CountMethod
四、路由
- 前端路由功能:让用户从一个视图(组件)导航到另一个视图(组件)
- 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
- 使用React路由简单来说,就是配置路径和组件
npm i -S react-router-dom
使用路由
1、定义路由模式 index.js
import React from 'react' import reactDom from 'react-dom' import App from './App.jsx' // 全局共享store import { Provider } from 'react-redux' import {HasRouter as Router} from 'react-router-dom' import store from './store' reactDom.render( <Provider store={store}> <Router> <App /> </Router> </Provider>, document.querySelector('#root')
2、定义路由导航
import React,{COmponent} from 'react' import { Route } from 'react-router-dom' // 导入相关模块 import Home from './views/home' import News from './views/News' class App extends Comment{ constructor(props){ super(props) } render(){ return( <> {/* path:路径 component:渲染的组件 exact:严格匹配 */} <Route exact path='/' component={Home}></Route> <Route path='/news' component={News}></Route> </> ) } }
声明式导航
使用Link或NavLink组件完成
Link :组件最终会渲染为 HTML 标签 <a>
NavLink:给已经渲染的元素添加参数
// react中的路由规则都是以组件的方式定义 import { Route, Link, NavLink } from 'react-router-dom' // 导入渲染的视图组件 import Home from './views/Home' import News from './views/News <li><NavLink exact activeClassName="active" to="/">首页</NavLink></li> <li><NavLink activeClassName="active" to="/news">新闻列</NavLink></li> {/* path访问的uri路径 component就是匹配成功后渲染的组件 */} {/* exact 严格匹配 */} {/* Rouet组件中匹配成功的渲中会自动在this.props添加路由导航相关属性方法 */} <Route exact path="/" component={Home} /> <Route path="/news" component={News} />
路由参数
<Route path=’/aa/:id’ component={Main}>
- params
在路由目标页面中通过 this.props.match.params
- query
通过地址栏中的 ?key=value&key=value,通过 this.props.location.search
- state
隐式转参,一点用于数据的收集 this.props.location.state
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律