本文最后更新于 2024-03-22T23:32:48+00:00
                  
                  
                
              
            
            
              
                
                发展要史 1、JS 能操作 DOM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <div id="app" >  <h1 > Hello</h1 >    <h2 > my name is</h2 >    <h3 > react</h3 >  </div>function  createElememt (tag, props, children ) {   const  el = document .createElememt (tag)   Object .entries (props).forEach (([key, value] ) =>  {     el.setAttribute (key, value)   })   children.forEach (child  =>  el.appendChild (child)) }createElememt ('div' , { id : 'app'  }, [   createElememt ('h1' , null , ['Hello' ]),   createElememt ('h2' , null , ['my name is' ]),   createElememt ('h3' , null , ['react' ]), ])
 
2、根据createElememt就能生成对应的 DOM 结构,但发现有点麻烦,所以 React 让 Babel 帮忙实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const  App  = ( ) => (   <div  id ="app" >    <h1 > Hello</h1 >      <h2 > my name is</h2 >      <h3 > react</h3 >    </div >   )const  App  = ( ) => React .createElement ("div" , { id : "app"  },   React .createElement ("h1" , null , "Hello" ),   React .createElement ("h2" , null , "my name is" ),   React .createElement ("h3" , null , "react" ) );
 
总结:React 核心是写 HTML 片段(JSX),然后让 Babel 编译为可执行的渲染函数,调用该函数能创建 DOM,但 React 做的事情不止于此,但可以这样简单的理解。
基础 创建一个基础的 React 项目
1 npx create-react-app projectName
 
组件分类 类组件 基础写法 1 2 3 4 5 6 import  React , { Component  } from  'react' export  default  class  ClassComName  extends  Component  {   render ( ) {     return  <div > I am Class Component</div >    } }
 
响应式数据写法 this.state、this.setState
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import  React , { Component  } from  "react" ;export  default  class  ClassComName  extends  Component  {   constructor ( ) {     super ();     this .state  = {       name : "Class Component~" ,       number : 1 ,     };   }   handleClick ( ) {     this .setState ({ number : this .state .number  + 1  });   }   render ( ) {     return  (       <div >         <h1 > I am 【{this.state.name}】</h1 >          <button  onClick ={()  =>  this.handleClick()}>Add Number</button >          <div > Number: {this.state.number}</div >          <hr  />        </div >       );   } }
 
父子传参 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import  React , { Component  } from  "react" ;export  default  class  ClassComName  extends  Component  {   constructor (props ) {     super (props);      this .state  = {       name : "Class Component~" ,       number : props.initNumber ,      };   }   handleClick ( ) {     const  number  = this .state .number  + 1 ;     this .setState ({ number  });           this .props .callback (number , this .state .name );   }   render ( ) {     return  (       <div >         <h1 > I am 【{this.state.name}】</h1 >          <div > props: {JSON.stringify(this.props)}</div >          <button  onClick ={()  =>  this.handleClick()}>Add Number</button >          <div > Number: {this.state.number}</div >          <hr  />        </div >       );   } }
 
生命周期 初始化阶段 constructor:初始化调用,初始化实例状态(state)和绑定事件处理器,不推荐在这里做数据获取或订阅操作。static getDerivedStateFromProps:在实例创建及后续每次 props 改变时都会调用,返回对象将与当前 state 合并,生成新的 statecomponentWillMount:已弃用 ,渲染之前执行,若有了getDerivedStateFromProps或getSnapshotBeforeUpdate时不执行render:执行,生成新的虚拟 DOM 用于 DIFF(若需要),但还未去更新 DOM 哦componentDidMount:渲染完成时调用,常用于网络请求、订阅或者手动 DOM 操作等。
更新阶段 componentWillReceiveProps:已弃用 ,props 改变时触发,建议用getDerivedStateFromPropsshouldComponentUpdate:更新拦截,根据返回的布尔值决定是否更新。可用于数据提交中时锁定其他操作componentWillUpdate:已弃用 ,更新前调用,建议用getSnapshotBeforeUpdaterender:执行,生成新的虚拟 DOM 用于 DIFF(若需要),但还未去更新 DOM 哦getSnapshotBeforeUpdate:获取更新 DOM 前的快照,获取元素某些信息(如滚动位置)componentDidUpdate:更新完成时调用,谨慎调用setState会触发重新渲染
销毁阶段 componentWillUnmount:销毁之前调用,用于清理任何定时器、取消网络请求、解绑事件监听器等资源清理工作。
函数式组件 基础写法 1 2 3 export  default  function  FuncComName ( ) {   return  <div > I am Function Component</div >  }
 
响应式数据写法 useState
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import  { useState } from  "react" ;export  default  function  FuncComName ( ) {   const  [name] = useState ("Function Component~" );   const  [number , setNumber] = useState (1 );   const  handleClick  = ( ) => {     setNumber (number  + 1 );   };   return  (     <div >       <h1 > I am 【{name}】</h1 >        <button  onClick ={()  =>  handleClick()}>Add Number</button >        <div > Number: {number}</div >        <hr  />      </div >     ); }
 
父子传参 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import  { useState } from  "react" ;export  default  function  FuncComName (props ) {    const  [name] = useState ("Function Component~" );   const  [number , setNumber] = useState (props.initNumber );    const  handleClick  = ( ) => {     const  _number = number  + 1 ;     setNumber (_number);          props.callback (_number, name);   };   return  (     <div >       <h1 > I am 【{name}】</h1 >        <div > props: {JSON.stringify(props)}</div >        <button  onClick ={()  =>  handleClick()}>Add Number</button >        <div > Number: {number}</div >        <hr  />      </div >     ); }
 
生命周期 函数式组件是没有生命周期的,只有一些钩子函数来替代生命周期。
useEffect 处理副作用。
1 2 3 useEffect (fun, deps) fun:它的返回值将在下一次 fun 执行前调用 deps:数组,当值改变时,执行上一次的 fun 返回值,然后再执行 fun
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21       useEffect (() =>  { console .log ('getDerivedStateFromProps' ) }, [])      useEffect (() =>  { console .log ('getDerivedStateFromProps' ) }, [props])      useEffect (() =>  { console .log ('componentDidMount' ) }, [])      useEffect (() =>  {     return  () =>  {       console .log ('componentWillUnmount' )     }   }, [])      useEffect (() =>  {   console .log ('componentDidUpdate' )   })
 
补充知识 Fiber 参考资料:万字长文介绍 React Fiber 架构的原理和工作模式 带你彻底读懂 React VDOM DIFF - 掘金  Fiber:本质是 JS 对象,也可以称为 React 版的虚拟 DOM。链表结构
Vue vs React Vue:使用 template,写法比较固定,但编译时可以做很多优化。 React:使用 JSX,写法非常灵活