class组件与函数hooks组件的写法
//class写法
import React, {Component} from 'react'
class Test extends Component(){
constructor(props){
super(props)
this.state = { count:0 }
}
render(){
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick = {this.addCount.bind(this)}>Click me</button>
</div>
)
}
addClick(){
this.setState({count:this.state.count + 1})
}
}
export default Test
//hooks写法
import React, {useState} from 'react'
function Test(){
const [count, setCount] = useState(0)
return (
<div>
<p>You clicked {count} times</p>
<button onClick = {()=>{setCount(count+1)}}>Click me</button>
</div>
)
}
export default Test
Hooks API
useState
const [count, setCount] = useState(0) //简单声明,其中useState参数为count初始值,setCount为改变数据函数
//不用结构赋值
let _useState = useState(0)
let count = _useState[0]
let setCount = _useState[1]
useEffect
import React, {useEffect} from 'react'
function Test(){
useEffect(()=>{
console.log(1111) //相当于componentDidMount与componentDidUpdate的结合,用于处理副作用与替代生命周期函数
})
}
实现componentWiiUnmount,在组件销毁前取消绑定
useEffect(()=>{
return ()=>{ //useEffect可以返回一个函数,在组件更新/销毁时执行
console.log("逻辑执行")
}
}, []) //数组为空的时候意味只有组件销毁的时候执行return的函数,有值则代表那个值变化时执行
useContext
用于解决父子组件传值的问题,其可访问全局
import React, { useState, createContext, useContext } from 'react'
const CountContext = createContext() //创建一个上下文对象
//父组件
function Father(){
const [count, setCount] = useState(0)
return (
<div>
<p>You clicked {count} times</p>
<button onClick = {()=>{setCount(count+1)}}>Click me</button>
<CountContext.Provider value={count}> //value为共享出去的数据
<Child />//需要传值的子组件
</CountContext>
</div>
)
}
//子组件
function Child(){
let count = useContext(CountContext)
return (<h2>{count}</h2>) //此处的count为接收到的参数
}
useReducer
//js版本的Reducer
function countReducer(state, action){ //state为传入的需要改变的参数,action为具体的操作
switch(action.type){
case 'add':
return state + 1
case 'sub':
return state - 1
default:
return state
}
}
//使用useReducer
import React, { useReducer } from 'react'
function ReducerDeemo(){
const [count, dispatch] = useReducer((state, action)=>{ //使用useReducer包裹
switch(action){
case 'add':
return state + 1
case 'sub':
return state - 1
default:
return state
}
}, 0)
return(
<div>
<h2>count:{count}</h2>
<button onclick={()=>{dispatch('add')}}></button> //通过dispath传入的参数实现不同操作
<button onclick={()=>{dispatch('sub')}}></button>
</div>
)
}
useReducer与useContext实现Redux效果
boundary-start ---UI---
//UI部分
import React, { useContext } from 'react'
import { Color, ColorContext, UPDATE_COLOR } from 'color.js' //由于没有使用默认样式,Color组件必须使用 {} 进行引入
//字体展示部分
function TextArea(){
const {color} = useContext(ColorContex)
return(
<div style={{color:color}}>字体显示</div>
)
}
//按钮部分
function Button (){
const {dispatch} = useContext(ColorContext)
return (
<div>
<Color> //使用context组件包裹,实现color的共享
<button onClick={()=>{dispatch({type:UPDATE_COLOR,color:'red'})}}>红色</button>
<button onClick={()=>{dispatch({type:UPDATE_COLOR,color:'yellow'})}}>黄色</button>
</Color>
</div>
)
}
//主体结构
function Main(){
return(
<div>
<TextArea />
<Button />
</div>
)
}
boundary-end ------
boundary-start ---创建context---
//创建context
import React, { createContext, useReducer } from 'react'
export const ColorContext = createContext({}) //生成一个context对象
export const UPDATE_COLOR = "UPDATE_COLOR" //建立操作常量,不容易出错
const reducer = (state, action) => {
switch(action.type){
case UPDATE_COLOR:
return action.color
default:
return state
}
}
export const Color = props=>{
const [color, dispatch] = useReducer(reducer, 'blue') //dispatch为派发器负责处理响应
return (
<ColorContext value={{color,dispatch}}>
{props.children}
</ColorContext>
)
}
boundary-end ------
_useMemo
boundary-end ------
其通过按条件阻止组件渲染解决Hooks的性能问题,主要替代shouldComponentUpdate
父组件发生任意变化都会影响子组件导致子组件更新并重新渲染,因此会产生严重的性能问题
import React, { useMemo } from 'react'
const test = useMemo(()=>fun(),[]) //参数一为限制执行的函数,参数二为监控的状态,只有被监控的状态改变时函数才执行
_useRef
其用于获取jsx中的DOM或是保存变量
函数组件与类组件区别
函数组件会捕获渲染帧的数据,类组件由于this指向问题导致获取的是最新渲染帧的数据(props)
尽管优化策略有些许不同,但性能的差异几乎可以忽略不计
经典例子:延迟三秒打印props中的数据
//函数组件
function ProfilePage(props) { //原先hooks没有推出时函数组件又被称为无状态组件,此处的参数为外部传入
const showMessage = () => {
alert('Followed ' + props.user);
};
const handleClick = () => {
setTimeout(showMessage, 3000); //延迟三秒打印数据
};
return (
<button onClick={handleClick}>Follow</button>
);
}
//函数组件在点击按钮并切换数据后依旧打印切换前的数据
//类组件
class ProfilePage extends React.Component {
showMessage = () => {
alert('Followed ' + this.props.user);
};
handleClick = () => {
setTimeout(this.showMessage, 3000); //注意此处的this指向,回调函数执行时其this指向的是三秒后的props
};
render() {
return <button onClick={this.handleClick}>Follow</button>;
}
}
//类组件在点击按钮并切换数据后打印切换后的数据,这种情况相当于获取到了"未来"的数据
类组件可以通过闭包解决这个问题
class ProfilePage extends React.Component {
render() {
// 通过在render中绑定props捕获当前帧数据
const props = this.props;
const showMessage = () => {
alert('Followed ' + props.user); //此时的数据为被绑定的数据
};
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return <button onClick={handleClick}>Follow</button>;
}
}
函数式组件也可以通过ref来达到获取"未来数据的效果"
function MessageThread() {
const [message, setMessage] = useState('');
// Keep track of the latest value.
const latestMessage = useRef('');
useEffect(() => {
latestMessage.current = message; //获取到最新渲染帧的数据
});
const showMessage = () => {
alert('You said: ' + latestMessage.current);
};