React中提供了两种创建自定义组件的语法:
语法一:函数式组件(Function Component)
function 组件名(props){ return JSX } |
let child = <组件名></组件名> let child = <组件名/> |
提示:JSX要求自定义组件名必须首字母大写
语法二:类式组件(Class Component)
class 组件名 extends React.Component{ render(){ return JSX} } |
let child = <组件名/> //底层会自动创建出类的实例 let child = <组件名></组件名> //底层会自动创建出类的实例 |
扩展:(
JSX: JavaScriptXML,使用XML的语法来创建JS对象 —— 这种语法来自于TypeScript,是TS语法的一部分;很早就已经有了,直到在React中发扬光大。
注意:浏览器不能直接执行TS(JSX)语法,必需使用TS语法编译器,转换为浏览器可以理解的语法。
在HTML中直接使用Babel编译JSX的语法:
<script src="js/babel.js"></script> <script type="text/babel"> //此处就可以编写变种JS代码了,例如TS(JSX) </script> |
注意:Babel编译出来的代码都是运行于严格模式下的("use strict") |
JSX语法汇总:
①JSX的语法属于XML语法,比HTML更加的严格
②一段JSX有且只有一个根元素
③JSX严格区分标签名和属性的大小写
④标签必须闭合,例如<br>必须写作 <br></br>或者<br/>
⑤JSX中可以进行数据绑定,语法:{ },不是{{ }},其中可以绑定JS变量或JS表达式或JS注释
⑥JSX中也可以出现注释,形如:{/* 注释内容 */}
⑦JSX中标签的属性与HTML类似,但是不完全一样,例如:class要写作className,onclick要写作onClick
⑧所有的JSX都必须使用Babel编译为浏览器可以执行的代码:React.createElement( ),创建出虚拟DOM对象
⑨React项目可以不使用JSX,但是使用了会变得更加简单
)
class组件的生命周期方法:
挂载阶段:
constructor():构造方法
render():渲染内容(第一次挂载时渲染)
comontentDidMount():组件挂载完成
更新阶段(props或state改变):
shouldComponentUpdate():应该让组件更新吗?即数据发生改变了,此次改变应该渲染 出来吗?
render():渲染内容(数据发生改变需要重新渲染)
componentDidUpdate():组件完成更新
卸载阶段:
componentWillUnmount():组建即将卸载
函数式组件 和 Hook
React中早期的函数式组件功能很“渣”,有两个严重缺陷:
function BuyCount( props ){ return JSX }
没有状态(state),不能渲染变化的数据 没有生命周期方法
只能用来写一些非常简单的不会发生改变的静态组件!!!
React V16.8开始,官方为函数式组件增加了新的特性,彻底弥补了之前的不足;加上函数式组件天然的优势(没有this),程序员们开始偏向于使用函数式组件!!!
Hook:钩子,本质就是一个函数,只要执行起来,就能为当前组件增加新的功能。
特点:
名称都以 use- 开头,例如:useState()、useEffect()、useRef()、useContext()....
只能在函数式组件内使用,不能在类式组件中使用
只能在组件内的最顶层使用,不能在内部使用
function 组件名 ( ){ let age = 20 useRef( ) //正确 if(){ useRef() } //错误 for(){ useRef() } //错误 function(){ useRef() } //错误 } |
React官方提供的常用钩子函数(总共有15个)
useState( ):为函数式组件增加“状态数据”的功能
import {useState} from 'react' let [状态变量名, 修改状态变量的方法名] = useState( 状态变量的初始值 ) |
说明:useState()返回的第二数据(是个方法)可用于修改第一个数据,与setState()类似,也是异步的;但是此方法只能用于修改数据,不能用于查看修改后的数据(没有第二个回调参数)——如果希望查看修改后的数据,请使用useEffect( )
useEffect( ):副作用/辅助功能钩子(例如:在组件挂载时异步请求服务器端数据、在组件卸载是清理组件内创建的定时器....), 可以为函数式组件增加“生命周期方法”的功能
//生命周期方法1 —— 关注的是:任意的新数据被渲染出来时 useEffect( ()=>{ console.log('生命周期方法1 —— 组件挂载时 或 任意数据更新时 执行') } ) |
//生命周期方法2 —— 关注的是:指定的新数据被渲染出来时 useEffect( ()=>{ console.log('生命周期方法2 —— 组件挂载时 或 指定数据更新时 执行') } , [ 依赖数据项1, 依赖数据项2, ... ] ) |
//生命周期方法3 —— 关注的是:组件挂载时 useEffect( ()=>{ console.log('生命周期方法3 —— 组件挂载时 执行') } , [ ] ) //依赖列表为空 |
//生命周期方法4 —— 关注的是:任意的旧数据被卸载时 useEffect( ()=>{ return ()=>{ console.log('生命周期方法4 —— 任意旧数据即将更新时 或 组件即将卸载时 执行') } } ) |
//生命周期方法5 —— 关注的是:指定的旧数据被卸载时 useEffect( ()=>{ return ()=>{ console.log('生命周期方法5 —— 指定旧数据即将更新时 或 组件即将卸载时 执行') } } , [依赖的数据项1, 依赖的数据项2, ....]) |
//生命周期方法6 —— 关注的是:组件即将被卸载时 useEffect( ()=>{ return ()=>{ console.log('生命周期方法6 —— 组件即将卸载时 执行') } } , [ ]) //依赖列表为空 |