React内容
React Fiber 16版本
registerServiceWorker 的作用
PWA progressive web application 写手机app应用 在断网的情况下,第二次访问会缓存
ReactDOM.render 会把组件挂载到真实DOM节点上
JSX语法 js里面写html + 自定义组件(自定义组件名称必须大写)
bind(this, index) 可以在bind里面传递参数
list.splice(index, 1) 删除一项
state 不允许直接做任何改变 不要 this.state.list.splice(index, 1)
解析 html 可能存在XSS攻击
<li dangerouslySetInnerHTML = {{ __html:item }}>
label扩大点击区域
<label htmlFor="inputa">输入内容</label>
<input id="inputa"/>
render 返回的内容 注释和其他部分不能是同一级别
不允许在子节点中直接修改父组件中的state
样式引入放在最后面
this.setState((prevState)=>{ return {value:e.target.value} // 需要提前获取value }) 否则可能会有问题
直接操作DOM, 是命令式编程, 大部分都在进行DOM操作
声明式编码 数据驱动
单向数据流:父组件传值给子组件 子组件只能使用而不能改变
否则会报错
好处是不容易出错, 因为可能在多个子组件中修改父组件的数据,可能导致出错
函数式编程给测试带来了便捷
propTypes和defaultProps import PropTypes from 'prop-types'; // 规定类型 TodoItem.propTypes = { test:PropTypes.string.isRequired, content: PropTypes.string, handItem: PropTypes.func, idx: PropTypes.number } // 默认值 TodoItem.defaultProps = { test:"hello,world" }
PropTypes.arrayOf(string,number) 数组的内容类型
oneOfType([string,number]) 才是 多种类型的一种
props state 与 render函数的关系
当组件的state或者 props发生变化的时候 render方法重新直接
当组件的render方法被执行时,它的子组件的render方法也会被执行
生成DOM替换原来的DOM都会非常消耗性能
一点点改变 都会导致新DOM的生成
改变:新生成的DOM和原来的DOM做对比找差异
只替换改变的DOM部分
缺陷:性能提升并不明显
改进:生成虚拟DOM(虚拟DOM就是一个js对象,用它来描述真实DOM)
<div id=’abc’>aaa</div> React.createElement(“div”, {id:’abc’}, abc)
数据发生了改变,生成新的 虚拟DOM
然后和原来的 虚拟DOM做对比
通过diff算法,找到不同的部分,然后直接操作DOM替换改变的部分
js生成一个js对象代价小,但是生成一个DOM代价高
只要和DOM相关的操作都极大消耗性能(不管是比较还是生成)
用虚拟DOM的结构生成真实DOM
jsx --> createElement 方法 --> 生成虚拟DOM(js对象) --> 真实DOM
该方法偏向底层 和<div>aaa</div> 效果是一样的 只是这么写比较简便
jsx 语法并不是真实的DOM,只是一个模板
所以就算没有jsx语法 也可以通过 createElement来替代
虚拟DOM生成在前 真实DOM生成在后
虚拟DOM的好处:
1.性能提升了
2.它使得跨端应用得以实现 (虚拟DOM 并不生成真实DOM) 而生成原生应用的组件
Diff算法 对比虚拟DOM (js对象)
1. 同级比对 + key 值比对
如果一致 继续比对第二层
如果不一致 则不再进行下一层的比对
好处是:比对算法比较简单
为什么setState 要设计成异步函数
多次短时间的操作可以合并成一次操作 减少对比虚拟DOM的次数
循环的时候 key的意义 比对和 key 值做关联
为什么key值 不要设置为 index
因为插入数组元素的时候 div 的index可能 改变成其他div的index
导致 key值不稳定 就失去了存在的意义
react中ref的使用
<input ref={ inp=> this.inp = inp }>
在使用的时候,直接使用 this.inp即可
不推荐使用ref
注意:ref和setState一起使用的时候可能导致结果不正确
因为setState 是异步的
this.setState((prevState)=>{}, ()=>{}) 第二个参数的意思是setState 执行完成之后,执行某些操作
这样就可以保证在更新完数据以后正确的执行某些操作
声明周期函数:
componentWillReceiveProps(props)
当一个组件从父组件接受参数 ==> 执行的时机
只要父组件的render函数重新被执行了,子组件的render函数也会被执行
换个说法
如果这个组件第一次存在组件中,不会被执行
如果这个组件之前已经存在于父组件中,才会被执行
当一个组件是父组件没有props值就不会被执行
shouldComponentUpdate 返回 bool
只会执行一次
componentWillMount / componentDidMount / componentWillUnmount
生命周期函数的使用场景
1. input 值改变,就会导致state改变 页面重新渲染
浪费了性能 使用shouldComponentUpdate
shouldComponentUpdate(nextProps,nxtState){ return nextProps.content !== this.props.content? true:false; }
在发送ajax请求的时候, 不能放在render方法中,因为render可能会被反复执行
componentDidMount 最好
componentWillMount 可能和react native 有冲突
使用Charles进行接口数据模拟 componentDidMount(){ axios.get('/api/todoList') .then((res)=>{ this.setState(()=>({list:[...res.data]})); tools – map local
css过渡动画 render(){ return <Fragment> <div className={ this.state.isShow? "show":"hide"}>hello,React</div> <button onClick={ this.handlerClick }>toogle</button> </Fragment> } .show { opacity: 1; transition: all 1s ease-in; } .hide{ opacity: 0; transition: all 1s ease-in; }
动画效果 通过@keyframes来定义动画 .hide{ animation: hide-item 2s ease-in forwards; } 加上forwards的作用是 保存动画最后一帧的CSS样式 @keyframes hide-item{ 0%{ opacity: 1; color: red; } 50%{ opacity: 0.5; color: green; } 100%{ opacity: 0; color: blue; } } 入场也是一样 反过来就可以了
使用react-transition-group 实现动画 yarn add
redux基础
组件树复杂的时候,组件传值非常麻烦
数据放在公共区域,而不是放在组件上
直接改变store里面的数据,组件就会自动感知到
Redux = Reducer + Flux
react是和Flux一起放出来的 Flux不是特别好用
Reducers 记录本
Component --> ActionCreators --> store --> Reducers --> Store --> Components
constructor(props){ super(props); this.state = store.getState(); }
reducer的限制: reducer可以接收 state,但是绝对不要修改 state
newState 返回给了 Store
store.subscribe(()=>{this.setState(store.getState()) }) 这个组件去订阅store
handlerChange(e){ const action = { type: 'change_input_value', value: e.target.value }; store.dispatch(action); //将action传递给 store } 然后store就会自动把 action转发给reducer if(action.type === 'change_input_value'){ const newState = JSON.parse(JSON.stringify(state)); newState.inputVal = action.value; return newState; }
return 返回回来的数据 就会给 store 然后store替换原来的数据
UI组件和容器组件的拆分
ui组件页面的渲染 傻 只管页面 不管逻辑
容器组件 聪明 不管页面 只管逻辑
无状态组件性能比较高, 它就是一个函数
而普通组件要执行一些生命周期函数
可以用于UI组件中
Redux 设计和使用的三大原则
1.store是唯一的 只有改变store能够改变自己的内容
2. reducer是纯函数 (固定的输入差生固定的输出, 没有副作用)
所以里面不能有异步操作和时间相关的操作
例如: newState.date = new Date() 或者对参数直接进行修改 state.inputValue = action.value
是store拿到reducer返回的数据 然后store来进行更新
而不是reducer改版数据的 这也是为什么reducer一定不要直接改变store里面的数据
redux 中发送异步请求获取数据 放在组件的componentDidMount
使用redux-thunk 把异步的代码从组件的DidMount 中移除到action里面去
const composeEnhancers = typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose; const enhancer = composeEnhancers( applyMiddleware(thunk,…), ); const store = createStore(reducer,enhancer);
componentDidMount(){ const action = getInitData();//返回的是一个函数 store.dispatch(action); // 这一步就会发异步请求 当返现action是一个函数,那么就会执行一下这个函数 }
componentDidMount(){ const action = getInitData();//返回的是一个函数 store.dispatch(action); // 这一步就会发异步请求 当返现action是一个函数,那么就会执行一下这个函数 }
如果把异步请求的方法都放在组件的生命周期函数里面, 那么内容会越来越多,而且更加方便测试(测试函数比测试生命周期函数简单)
redux的中间件
中间指的是 action 和store的中间 只是对dispatch的升级
reset.css 加入到全局样式中去,在不同的内核上 不同的 标签的表现形式可能不同
background-size: contain 表示让图片包含在div中 正常大小
react只兼容到 IE8
create-react-app 有一个特性 在public下面 定义api目录 可以当做 请求地址模拟后端请求访问
render 方法 可以返回一个数组 和字符串
React16.4 中废弃了一些生命周期函数
componentWillUpdate componentWillReceiveProps
res.send / res.json / res.sendfile 响应不同的内容
回到顶部功能
window.scrollTo(0,0)
每一个组件都调用了 connect方法 和store进行了连接,只要每一个数据发生了改变
那么每一个组件都会被重新渲染 这样不好 例如 input框里面的数据改变
性能很低:
在组件里面 都加上 componnentWillUpdate() 只要和自己相关的数据 就会返回 true 无关的就会返回false
将继承Component 都改为PureComponent 用了该组件就需要使用 immutable来管理数据 否则会出现坑
页面的跳转不要使用 a 标签 会加载 html 会消耗性能
import { Link } from ‘react-router-dom’
<Link to = ‘/detail’>
获取路由参数
<Link to=”/detail/:id”>
<Link to={ “/detail/” + “abc”>
<Route path=”/detail/:id”>

第二种方式 <Link to={ “/detail?id=” + “abc”> <Route path=”/detail”> 这样就可以匹配到了 this.props.location.search 还要自己去解析这个字符串
styled-component 要通过 innerRef 得到原始的DOM结构
异步组件 yarn add react-loadable
第一个参数是要加载的组件 第二个参数是加载过程中显示的组件
axios 拦截器
在使用express中使用 cookie 依赖 cookie-parse
1. swiper loop 设为 true 时,同时有改变了 slidePreview 的值,这时轮播时,按prev按钮到第一个时
会出现空白页 解决办法: slidePrerview 设置为 auto loopSliders 设置为你要显示的 slide个数
2. swiper-slide 为动态添加的内容 时 swiper的滑动效果会消失
解决办法: 初始化中设置 observer 为true observerParent 为true
componentDidCatch(error, errorInfo){} 出错的生命周期函数
【推荐】国内首个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 绘制太阳,地球,月球 运作规律