持续补充中…
简介
由Facebook开源的,用于动态构建用户界面的 JavaScript 库(只关注于视图)。具有如下特点: 1.声明式编码 2.组件化编码 3.React Native 编写原生应用 4.高效(优秀的Diffing算法)
React高效的原因:
1.使用虚拟(virtual)DOM, 不总是直接操作页面真实DOM。 2.DOM Diffing算法, 最小化页面重绘。
虚拟DOM
创建虚拟DOM
React.createElement(component, props, ...children)
const VDOM = React.createElement('h1',{id:'title'},'<span>this is a virtal children dom</span>')
const VDOM = <h1 id='title'><span>this is a virtal children dom</span></h1>
渲染虚拟DOM
ReactDOM.render(virtualDOM, containerDOM)
ReactDOM.render(VDOM, document.getElementById('app'))
React脚手架
npx create-react-app [project name]
脚手架初始化的目录结构:
public ---- 静态资源文件夹
favicon.icon ------ 网站页签图标
index.html -------- 主页面
logo192.png ------- logo图
logo512.png ------- logo图
manifest.json ----- 应用加壳的配置文件
robots.txt -------- 爬虫协议文件
src ---- 源码文件夹
App.css -------- App组件的样式
App.js --------- App组件
App.test.js ---- 用于给App做测试
index.css ------ 样式
index.js ------- 入口文件
logo.svg ------- logo图
reportWebVitals.js --- 页面性能分析文件(需要web-vitals库的支持)
setupTests.js ---- 组件单元测试的文件(需要jest-dom库的支持)
函数式组件
函数组件又称为无状态组件,不能使用state ,只可以使用只读的props :
function App(props) {
return (
<>
hello react
</>
);
}
Hooks:
Hook是React 16.8.0版本增加的新特性/新语法,可以让我们在函数组件中使用 state 以及其他的 React 特性。
React.useState() :
State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作:
const [xxx, setXxx] = React.useState(initValue)
setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
React.useEffect() :
Effect Hook 可以让我们在函数组件中执行副作用操作(模拟类组件中的生命周期钩子):
useEffect(() => {
console.log('do something here')
return () => {
console.log('do something here')
}
}, [stateValue])
React.useRef() :
Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据:
const refContainer = useRef()
React.useContext() :
祖孙组件之间传值:
React.userReducer() :
userReducer可以配合useContext实现类似redux的功能:
自定义Hook: React Hook只能在组件或者Hook中使用,Hook命名得以 use 开头,例如如下实现的两个自定义Hook:
export default useMounted = (callback) => {
useEffect(() => {
callback()
}, [])
}
export default useDebounce = (value, delay) => {
const [debounceValue, setDebounceValue] = useState(value)
useEffect(() => {
const timeout = setTimeout(() => setDebounceValue(value), delay)
return () => clearTimeout(timeout)
}, [value])
}
类式组件
组件3大核心属性
props: state: ref:
React路由
setState
1.对象式的setState:
setState(stateChange, [callback])
2.函数式的setState:
setState(updater, [callback])
总结:
1.对象式的setState是函数式的setState的简写方式(语法糖) 2.使用原则: (1).如果新状态不依赖于原状态 ,则使用对象方式 ; (2).如果新状态依赖于原状态,则使用函数方式 ; (3).如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中读取。
生命周期
生命周期的三个阶段:
-
初始化阶段: 由ReactDOM.render() 触发—初次渲染 1.constructor() 2.getDerivedStateFromProps 3.render() 4.componentDidMount() -
更新阶段: 由组件内部this.setSate() 或父组件重新render 触发 1.getDerivedStateFromProps 2.shouldComponentUpdate() 3.render() 4.getSnapshotBeforeUpdate 5.componentDidUpdate() -
卸载组件: 由ReactDOM.unmountComponentAtNode() 触发 componentWillUnmount()
常用和重要的钩子:
render()
componentDidMount()
componentWillUnmount()
React UI组件库 Antd
yarn add antd
组件使用和主题自定义参考官方文档:https://ant.design/index-cn
LazyLoad
const Login = lazy(()=>import('@/pages/Login'))
<Suspense fallback={<h1>loading.....</h1>}>
<Switch>
<Route path="/xxx" component={Xxxx}/>
<Redirect to="/login"/>
</Switch>
</Suspense>
Fragment
作用:可以不用必须有一个真实的DOM根标签了
<Fragment><Fragment>
<></>
Context
React中一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信。
const XxxContext = React.createContext()
<xxxContext.Provider value={父数据}>
子组件
</xxxContext.Provider>
static contextType = xxxContext
this.context
<xxxContext.Consumer>
{
value => (
要显示的内容
)
}
</xxxContext.Consumer>
在应用开发中一般不用context, 一般都用它封装react插件。
Redux
组件通信方式总结
组件间的关系:
- 父子组件
- 兄弟组件(非嵌套组件)
- 祖孙组件(跨级组件)
几种通信方式:
- props:children props 和 render props
- 消息订阅-发布:pubs-sub、event等等
- 集中式管理:redux、dva等等
- conText:生产者 - 消费者模式
推荐的搭配方式:
- 父子组件:props
- 兄弟组件:消息订阅-发布、集中式管理
- 祖孙组件(跨级组件):消息订阅 - 发布、集中式管理、conText(开发用的少,封装插件用的多)
Component优化
Component的2个问题:
-
只要执行setState(),即使不改变状态数据, 组件也会重新render() ==> 效率低 -
只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据 ==> 效率低
效率高的做法:
只有当组件的state或props数据发生改变时才重新render()
原因:
Component声明周期中的shouldComponentUpdate() 方法总是返回true
解决方法1:
重写shouldComponentUpdate() 方法,比较新旧state 或props 数据, 如果有变化才返回true , 如果没有返回false
解决方法2(推荐):
使用PureComponent 。PureComponent 重写了shouldComponentUpdate() , 只有state 或props 数据有变化才返回true 注意:
- 只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false
- 不要直接修改state数据, 而是要产生新数据
Error boundary(错误边界)
Error boundary 用来捕获后代组件错误,渲染出备用页面。但是只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
使用方式:getDerivedStateFromError 配合 componentDidCatch
static getDerivedStateFromError(error) {
console.log(error);
return {
hasError: true,
};
}
componentDidCatch(error, info) {
console.log(error, info);
}
使用自定义配置文件
项目根目录下,即和src 同级下创建.env 和.env.development 两个文件,分别表示生产环境和开发环境下的不同配置:
REACT_APP_TEST = hahaha
REACT_APP_TEST = lalala
配置文件中变量的命名规则为 REACT_APP_ + NAME ,如上述的:REACT_APP_TEST 。
读取配置文件和使用变量:
import React from 'react';
const Test = process.env.REACT_APP_TEST
export default function App() {
return (
<>
hello react
{console.log(process.env.NODE_ENV)}
{console.log(Test )}
</>
)
}
CSS IN JS
React默认集成了 module.js ,只需将原.css 后缀的样式文件改为.module.css 即可,通过 import 样式文件作为一个对象,然后调用对象属性的方式给 className 赋值实现样式添加:、
|