react是什么?
react是facebook内部创建的用于构建用户界面的javascript框架。
react代码库地址
https://github.com/facebook/react/
react官方文档
https://reactjs.org/
废话不多说,让我们创建一个项目来体验一下react。
创建命令
npx create-react-app my-app
react核心概念
函数组件和类组件
类组件
import React from "react";
export default class ClassSub extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
函数组件
export default function FunctionSub(props) {
return <h1>Hello, {props.name}</h1>;
}
生命周期
生命周期图解链接React Lifecycle Methods diagram,和官网的React.Component – React一样。
import React from "react";
export default class ClassSub extends React.Component {
constructor(props) {
super(props);
this.state={
count:0
}
console.log(1)
}
componentDidMount() {
console.log(3)
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
//可以做性能优化
console.log(4)
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(5)
let snap="react"
return snap;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(snapshot)
console.log(6)
}
render() {
console.log(2)
return <h1 onClick={()=>{this.setState({count:++this.state.count,})}}>Hello, {this.props.name},{this.state.count}</h1>;
}
}
添加图片注释,不超过 140 字(可选)
函数式组件生命周期
import {useEffect, useState} from "react";
export default function FunctionSub(props) {
let [count,setCount]=useState(0);
console.log(1)
useEffect(()=>{
console.log(2)
return ()=>{
console.log(4)
}
},[])
useEffect(()=>{
console.log(3)
})
return <h1>Hello, {props.name}</h1>;
}
添加图片注释,不超过 140 字(可选)
为什么会打印两次呢?这是react开发环境下的设置,在生产环境不会发生。由此可见,开发环境下,react是把组件渲染又销毁,完整的走了一遍生命周期。类组件下有时触发了打印两次,有时又没有,但是函数式组件刷新页面都能看到打印两次。
以上就是react的基本概念了。看到这里你就算是已经入门了。
自古以来,人们都喜欢偷懒。也可以说是为了提高效率。我们总是希望复用代码的逻辑,而不是cv。
组件复用
从上面的讲解,你大概已经猜到了。react界存在两派人物,一派是忠厚老实的类组件,一派是奸诈狡猾的函数式组件。
现在,老板出题了。我要在组件里拿到鼠标的位置,你们分别用你们的方式实现一下吧。
类组件
类马上想到了解决办法。在类里我可以利用高阶组件,传入一个组件,我改装一下,出厂就可以带上鼠标位置了。
import React from 'react'
export default function mouse(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
x:0,
y:0
};
this.getMousePosition=this.getMousePosition.bind(this)
}
componentDidMount() {
document.addEventListener('mousemove',this.getMousePosition)
}
componentWillUnmount() {
document.removeEventListener('mousemove',this.getMousePosition)
}
getMousePosition(e){
this.setState({
x:e.clientX,
y:e.clientY
})
}
render() {
return <WrappedComponent {...this.state} />;
}
};
}
import ClassSub from "./ClassSub";
import ClassSub2 from "./ClassSub2";
import mouse from "./high";
let C1 = mouse(ClassSub)
let C2 = mouse(ClassSub2)
function App() {
return (
<div>
<C1/>
<C2/>
</div>
);
}
export default App;
添加图片注释,不超过 140 字(可选)
类做完了。老板一看,满意地点了点头。
函数马上叫到:瞧你那别扭的熊样,这写的是人看的吗?我用hooks实现起来简洁明了。
类气得无话可说。老板高兴的说道:好,我们看看函数到底有啥妙招。
函数组件
import {useEffect, useState} from "react";
export default function useMouse(){
let [x,setX]= useState(0)
let [y,setY]= useState(0)
useEffect(()=>{
const mouse=(e)=>{
setX(e.clientX)
setY(e.clientY)
}
document.addEventListener('mousemove',mouse)
return ()=>{
document.removeEventListener('mousemove',mouse)
}
},[])
return [x,y]
}
函数很快完成了。的确是比较简单实用。老板随即宣布函数获胜。
总结
函数组件是react 16版本出的新的api。以简洁高效的复用功能,一经推出,就迅速风靡了前端领域。我觉得react好用的原因是可以用js的思维写组件。但是react一直以学习曲线陡峭著称,原因在于react内部处理的复杂性是一时半会难以理解的,以至于无法灵活使用。下次我们来深入react的源码,看看react内部有什么样的巧思和设计。
如果文章对你有帮助,欢迎一键三连。