这是我参与更文挑战的第15天,活动详情查看: 更文挑战
一、hooks介绍和应用场景
hooks是16.8之后出现的新特性,React团队希望,组件不要变成复杂的容器,最好只是数据流的管道。开发者根据需要,组合管道即可。组件最佳的写法是函数,而不是类。React早就支持函数组件,下面就是一个例子。
function Welcome(props) {
return <h1> Hello ,{props.name}</h1>
}
复制代码
但是这种写法有重大的限制,必须是纯函数,不能包含状态,也不支持生命周期方法,因此无法取代类。
React Hooks设计的目的,就是加强版的函数组件,完全不使用类,就能写出一个全功能的组件。
Hooks可以让无状态组件实现有状态组件的部分功能,比如设置state,使用钩子函数:
componentDidMount、componentDidUpdate、componentWillUnmount。
二、hooks中的useState
从useState中解构出属性和set属性方法
import React,{useState, useEffect} from 'react'
export default function Hooks() {
const [title,setTile] = useState('首页')
function changeTitle() {
setTile('改变title')
}
}
复制代码
三、hooks中的useEffect方法
useEffect可以获取改变了的属性
// 更新数据的回调处理 第一个参数cb方法 第二个参数需要使用的参数(优化, 不传也可以获取到) useEffect如果值相同就不会再执行了
useEffect(() => {
return () => {
// return中的cb方法相当于componentWillUnmount
document.title = title
console.log('componentWillUnmount...')
}
},
[title]
)
复制代码
例子
import React,{useState,useEffect} from 'react';
import Css from "./assets/css/app.css";
// 使用无状态组件
function App() {
const [title, setTitle] = useState('首页') // useState 解构属性和设置属性的方法
function changeTitle() {
setTitle('hooks')
}
// 更新数据的回调处理 第一个参数cb方法 第二个参数需要使用的参数(优化, 不传也可以获取到) useEffect如果值相同就不会再执行了
useEffect(() => {
return () => {
// return中的cb方法相当于componentWillUnmount
document.title = title
console.log('componentWillUnmount...')
}
},
[title]
)
return (
<div className={Css['app']}>
<div>{title}</div>
<button onClick={changeTitle.bind(this)}>改变title</button>
</div>
)
}
export default App;
复制代码
效果

四、useReducer
React本身不提供状态管理功能, 通常需要使用外部库. 这方面最常用的库是Redux。
Redux的核心概念是, 组件发出action与状态管理器通信。状态管理器收到action以后,使用Reducer函数算出新的状态,Reducer函数的形式是(state,action)=》 newState
例子:
新建一个处理useReducer方法的js
export let defaultState = {count: 0}
export let countReducer = (state =defaultState,action) =>
{
switch (action.type) {
case 'inc': // 增加
state = {...state, ...action.payload}
break;
case 'dec': // 减少
state = {...state, ...action.payload}
break;
}
return state
}
复制代码
然后在app.js中使用useReducer
import React,{useReducer} from 'react';
import Css from "./assets/css/app.css";
import {defaultState,countReducer} from './hooksReducer/reducerCount'
let iCount = 0
function App() {
let thing = useReducer(countReducer,defaultState)
let [state,dispatch] = thing
return (
<div className={Css['app']}>
计算:
<button onClick={()=> dispatch({type: 'dec', payload: {count: --iCount}})}>-</button>
{state.count}
<button onClick={()=> dispatch({type: 'inc', payload: {count: ++iCount}})}>+</button>
</div>
)
}
export default App;
复制代码
效果

五. useContext
相当于Vue中的bus在组件中通信
5.1 新建一个context.js文件
import React from 'react'
export default React.createContext()
复制代码
5.2 封装count组件
这里相当于消费者
import React,{useContext} from 'react';
import Context from '../../context'
function Count() {
let countContext = useContext(Context)
return (
<div>
子组件计算:
<button onClick={()=> countContext.dispatch({type: 'dec', payload: {count: --countContext.state.count}})}>-</button>
{countContext.state.count}
<button onClick={()=> countContext.dispatch({type: 'inc', payload: {count: ++countContext.state.count}})}>+</button>
</div>
)
}
export default Count;
复制代码
5.3 在app.js中使用context.js
这里相当于信息提供者
import React,{useReducer} from 'react';
import Css from "./assets/css/app.css";
import {defaultState,countReducer} from './hooksReducer/reducerCount'
import Context from './context'
import Count from './component/count'
let iCount = 0
function App() {
let thing = useReducer(countReducer,defaultState)
let [state,dispatch] = thing
return (
<div className={Css['app']}>
<Context.Provider value={{state,dispatch}}>
<Count></Count>
计算:
<button onClick={()=> dispatch({type: 'dec', payload: {count: --iCount}})}>-</button>
{state.count}
<button onClick={()=> dispatch({type: 'inc', payload: {count: ++iCount}})}>+</button>
</Context.Provider>
</div>
)
}
export default App;
复制代码
效果

六、hooks轮播图案例
6.1 app.js中
import React from 'react';
import Swiper from './components/swiper';
import Css from "./assets/css/app.css";
class App extends React.Component{
constructor(){
super();
this.state={
images:[],
images2:[]
};
}
componentDidMount(){
setTimeout(()=>{
let images=[
{src:require("./assets/images/banner1.jpg"),url:"https://pages.tmall.com/wow/a/act/tmall/tmc/23759/wupr?spm=875.7931836/B.2016006.d6.66144265aPX4zF&trackInfo=20160815100101;64866506034;287638;587431337429;3;287638_587431337429;1007.14152.68669.100200300000000;92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5;3;0;10000002&item_id=587431337429&pvid=92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5&pos=3&activity_id=287638&wh_pid=industry-170400&acm=07055.1003.1.2519102&scm=1003.1.20160815.OTHER_0_6801489"},
{src:require("./assets/images/banner2.jpg"),url:"https://pages.tmall.com/wow/a/act/tmall/tmc/23759/wupr?spm=875.7931836/B.2016006.d1.66144265aPX4zF&trackInfo=20160815100101;64950842484;288994;530549532317;3;288994_530549532317;1007.14152.68669.100200300000000;92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5;1;0;10000002&item_id=530549532317&pvid=92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5&pos=1&activity_id=288994&wh_pid=industry-170636&acm=07055.1003.1.2519102&scm=1003.1.20160815.OTHER_0_6810849"},
{src:require("./assets/images/banner3.jpg"),url:"https://www.tmall.com/wow/brand/act/fashion?acm=lb-zebra-2386-265936.1003.4.410386&scm=1003.4.lb-zebra-2386-265936.OTHER_1_410386&ali_trackid=19_4803ba43894904cab9c8c08820f2e4a5&spm=875.7931836/B.2016006.d2"}
];
this.setState({images:images});
let images2=[
{src:require("./assets/images/banner2.jpg"),url:"https://pages.tmall.com/wow/a/act/tmall/tmc/23759/wupr?spm=875.7931836/B.2016006.d6.66144265aPX4zF&trackInfo=20160815100101;64866506034;287638;587431337429;3;287638_587431337429;1007.14152.68669.100200300000000;92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5;3;0;10000002&item_id=587431337429&pvid=92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5&pos=3&activity_id=287638&wh_pid=industry-170400&acm=07055.1003.1.2519102&scm=1003.1.20160815.OTHER_0_6801489"},
{src:require("./assets/images/banner3.jpg"),url:"https://pages.tmall.com/wow/a/act/tmall/tmc/23759/wupr?spm=875.7931836/B.2016006.d1.66144265aPX4zF&trackInfo=20160815100101;64950842484;288994;530549532317;3;288994_530549532317;1007.14152.68669.100200300000000;92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5;1;0;10000002&item_id=530549532317&pvid=92ba02ea-a2a8-4bbe-99ac-d5c3abf2eba5&pos=1&activity_id=288994&wh_pid=industry-170636&acm=07055.1003.1.2519102&scm=1003.1.20160815.OTHER_0_6810849"},
{src:require("./assets/images/banner1.jpg"),url:"https://www.tmall.com/wow/brand/act/fashion?acm=lb-zebra-2386-265936.1003.4.410386&scm=1003.4.lb-zebra-2386-265936.OTHER_1_410386&ali_trackid=19_4803ba43894904cab9c8c08820f2e4a5&spm=875.7931836/B.2016006.d2"}
];
this.setState({images2:images2})
},400)
}
render(){
return (
<div className={Css["app"]}>
<div class={Css["banner"]}>
<Swiper data={this.state.images}></Swiper>
</div>
<div className={Css["banner"]}>
<Swiper data={this.state.images2}></Swiper>
</div>
</div>
)
}
}
export default App;
复制代码
6.2 封装的swiper hooks组件
index.js
import React from 'react';
import Hoc from './hoc';
import "./style.css";
export default Hoc((props)=>{
return(
<div className="my-swiper-main" onMouseOver={props.stop} onMouseOut={props.autoPlay}>
{
(props.data && props.data.length>0) && props.data.map((item,index)=>{
return (
<div className={item.active?"slide show":"slide"} key={index}>
<a href={item.url} target="_blank" rel="noopener noreferrer"><img src={item.src} alt=""/></a>
</div>
)
})
}
<div className="pagination">
{
(props.data && props.data.length>0) && props.data.map((item,index)=>{
return (
<div className={item.active?"dot active":"dot"} key={index} onClick={()=>{props.changeImg(index)}}></div>
)
})
}
</div>
</div>
)
})
复制代码
6.3 hoc.js
import React,{useEffect,useState,useRef,useCallback} from 'react';
import PropTypes from 'prop-types';
export default function Hoc(WithComponent){
function HocComponent(props){
let [data,setData]=useState([]);
let [isInit,setIsInit]=useState(true);
let [iIndex,setIndex]=useState(0);
//创建一个表示,通用的容器
let timer=useRef(null);
//点击切换图片
function changeImg(index){
setIndex(index);
if(data && data.length>0){
for(let i=0;i<data.length;i++){
if(data[i].active){
data[i].active=false;
break;
}
}
data[index].active=true;
setData(data);
}
}
//自动播放
const autoPlay=useCallback(()=>{
clearInterval(timer.current);
timer.current=setInterval(()=>{
let tmpIndex=iIndex;
if(data && data.length>0){
for(let i=0;i<data.length;i++){
if(data[i].active){
data[i].active=false;
break;
}
}
if(tmpIndex>=data.length-1){
tmpIndex=0;
}else {
tmpIndex++;
}
data[tmpIndex].active=true;
setIndex(tmpIndex);
setData(data);
}
},3000)
},[data,iIndex]);
//停止自动播放
function stop(){
clearInterval(timer.current);
}
useEffect(()=>{
if(props.data && props.data.length>0 && isInit){
setIsInit(false);
for(let i=0;i<props.data.length;i++){
if(i===0){
props.data[i].active=true;
}else{
props.data[i].active=false;
}
}
setData(props.data);
}
autoPlay();
//页面离开时执行
return ()=>{
clearInterval(timer.current);
}
},[props.data,isInit,autoPlay]);
let newsProps={
changeImg,
data,
stop,
autoPlay
};
return (
<WithComponent {...props} {...newsProps}></WithComponent>
)
}
HocComponent.propTypes={
data:PropTypes.array.isRequired
};
return HocComponent;
}
复制代码
效果

© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END





















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)