在React中,定义组件的方式一直有两种,一种类组件,一种函数式组件
类组件中有state、有this、有上下文、有ref、有生命周期等各种特性,所以类组件的运行性能比较差
函数式组件没有state、没有this、没有上下文、没有ref、没有生命周期等等,所以函数式组件的运行性能比较好。
无论是类组件还是函数式组件,都有props
- React(v15+) 普遍使用class类组件,它的背后是虚拟dom和diff运算
- React(v16) 从v16开始,React背后不再是简单的虚拟dom了,而是最新的Fiber架构
- React(v16.8+) 从16.8开始,React新增了Hooks API,这使得Hooks编程成为了可能
在React(v16.8)以前,我们在编写React组件时,会考虑是否要用到state。如果需要用到state,我们就使用类组件;反之,我们定义函数式组件。
随着React(v16.8)越来越普及,现在市场中呈现出“只使用函数式组件”的趋势,类组件越来越少了。但是React函数式组件没有state、没有生命周期等,怎么办?React(v16.8)新增的Hooks弥补了这些问题。
所以在编写React组件,都使用函数式组件,不再使用类组件了。当我们需要用到state、上下文和生命周期等特性时,我们使用Hooks API来模拟,这就是我们所谓的“Hooks编程”。
特别注意:在类组件中,不能使用Hooks API;在React(v16.8)以前,没有Hooks API。只有在React(v16.8)以后、并且只有函数式组件中才能使用Hooks API。
常用的Hooks API :
useState,useEffect, useContext,useMemo ,useCallback, useRef,useReducer,useLayoutEffect......
useState 用于定义声明式变量,当使用set*方法修改声明式变量时,组件会自动更新。
语法:const [num, setNum] = useState(初始值)
// 实现num自增和自减
const TestHooks = props=> {
// 这里编写代码逻辑
const [num, setNum] = useState(1)
return (
<div>
<h1>Hooks编程</h1>
<hr />
<h2>{num}</h2>
<button onClick={() => setNum(num + 1)}>自增</button>
<button onClick={() => setNum(num - 1)}>自减</button>
</div>
)
}
export default TestHooks
上述数组中的第二个变量是 '函数'类型,这个函数是修改第一个变量的专属方法,只有通过这个函数来修改声明式变量,视图才会自动更新
注意:第二个变量 "函数"的的调用是异步的(你可把它和类组件中的this.setState()进行结合思考);当我们调用第二个函数时,会触发整个函数式组件重新执行
// 实现添加任务列表功能
const TestHooks = props=> {
// 这里编写代码逻辑
const [list, setList] = useState([])
const [todo, setTodo] = useState('')
const confirm = (e) => {
if (e.keyCode === 13) {
// 把表单中的todo添加到list中
setList([...list, { id: Date.now(), todo }])
setTodo('')
}
}
return (
<div>
<h1>Hooks编程</h1>
<hr />
任务名称:<input type='text'
value={todo}
onChange={(e) => setTodo(e.target.value)}
onKeyUp={confirm}
/> <br />
<div>
{list.map(ele => (<div key={ele.id}>{ele.todo}</div>))}
</div>
</div>
)
}
export default TestHooks
实现效果: