1- hook
1- 什么是hooks?
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他 的 React 特性。
2- 主要解决的问题
1.用于在函数组件中引入状态管理和生命周期方法;
2.取代高阶组件和render props来实现抽象和可重用性;
3.完全脱离"类",便可写出一个全功能的组件。
3- 常用的钩子:
3-1 useState
作用: 使函数组件也可以拥有状态,后期状态更新时可以引起视图更新
import React,{useState} from 'react' export default function UseState() { // let name='小黑' // 第一个接收状态, 第二个接收 修改当前状态的方法 let [name,setName] = useState('小黑') // 可以多次调用 let [age,setAge] = useState(18) let[sex,setSex] =useState('男') let [state,setState] = useState({ name:'小黑', age:18, sex:'男' }) function changeName(){ // name='小白' setName('小白') console.log(name); } function changeObj(){ setState({ ...obj, age:99 }) } return ( <div className='box'> <h1>useState组件</h1> <button onClick={()=>changeName()}>修改name</button> <button onClick={()=>setName('小白')}>修改name</button> <h2>{name}</h2> <button onClick={()=>changeObj()}>修改age</button> <h2>{state.age}</h2> <h2>{state.sex}</h2> </div> ) }
3-2 useEffect
作用: 使函数组件有类似componentDidmount,componentDidUpdate,componentWillUnmount的功能
// 方式一: componentDidMount + componentDidUpdate // useEffect(()=>{ // console.log('useEffect触发'); // }) // 方式二:componentDidMount // useEffect(()=>{ // console.log('useEffect触发'); // },[]) // 方式三: componentDidMount, name状态更新是会触发 // useEffect(()=>{ // console.log('useEffect触发'); // },[name]) // 方式四: componentDidMount + componentDidUpdate + componentWillUnmount // return的函数时销毁之前触发 useEffect(()=>{ let timer = setInterval(()=>{ setTime(new Date()) },1000) return ()=>{ // 销毁之前清除定时器 clearInterval(timer) } })
3-3 useReducer
作用: 使函数组件有状态管理
// 状态管理 export let initState = { age:19, name:'小红' } const TYPES={ CHANGENAME:'CHANGENAME', CHANGEAGE:'CHANGEAGE' } export function reducer(state=initState,action){ switch(action.type){ case TYPES.CHANGENAME: return { ...state, name:action.name } case TYPES.CHANGEAGE: return { ...state, age:action.age } default: return { ...state } } } export const actions = { changeName:(name)=>({type:TYPES.CHANGENAME,name}), changeAge:(age)=>({type:TYPES.CHANGEAGE,age:age}) }
---组件
import React,{useReducer} from 'react' import {initState,reducer,actions} from './red' export default function UserReducer() { // 创建状态管理 let [state,dispatch] = useReducer(reducer,initState) function change(){ // 修改name // dispatch({type:'changeName',name:'小会'}) // 触发action,修改状态, 可以视图更新 dispatch(actions.changeName('小灰灰')) } return ( <div className='box'> <h1>UserReducer组件</h1> <button onClick={()=>change()}>修改name</button> <h1>{state.name}---{state.age}</h1> </div> ) }
3-4 useContext
作用: 多个组件之间状态传递
import React,{useReducer,createContext,useState} from 'react' import {initState,reducer,actions} from './red' import Child from './Child' export let myContext = createContext() export default function UserReducer() { // 创建状态管理 let [state,dispatch] = useReducer(reducer,initState) let [name,setName] = useState('小黑') function change(){ // 修改name // dispatch({type:'changeName',name:'小会'}) // 触发action,修改状态, 可以视图更新 dispatch(actions.changeName('小灰灰')) } return ( <div className='box'> <h1>UserReducer组件</h1> <button onClick={()=>change()}>修改name</button> <h1>{state.name}---{state.age}</h1> <myContext.Provider value={state}> <Child></Child> </myContext.Provider> </div> ) }
---后代组件接收
import React,{useContext} from 'react' import {myContext} from './UserReducer' export default function ChildChild() { // 接收provider发送的数据 let state = useContext(myContext) return ( <div className='box'> <h1>ChildChild组件</h1> <h1>{state.name}---{state.age}</h1> </div> ) }
4- hook注意
-
只在函数组件顶层使用,不可以在循环和条件或者嵌套函数中使用
-
只在react函数中调用。 不要用在普通的js函数中
2- 动画
1. 安装
npm i react-transition-group --save
2- 使用
-
unmountOnexit 结束时销毁, 必填属性
-
in 设置动画关联的状态 必填属性
-
timeout 动画时长 必填属性
-
classNames=‘f’ 设置动画的类名 必填属性
-
f-enter: 显示时,动画开始的状态
-
f-enter-active 显示时,动画的过程
-
f-exit: 消失时,动画的开始状态
-
f-exit-active 消失时,动画的过程
-
-
onEnter: 显示时,动画开始执行的回调函数
-
onEntering: 显示时,动画执行中的回调函数
-
onEntered; 显示时,动画执行结束的回调函数
-
onExit: 消失时,动画开始执行的回调函数
-
onExiting: 消失时,动画执行中的回调函数
-
onExited: 消失时,动画执行结束的回调函数
1- 单元素动画
<CSSTransition onExited={()=>{console.log('动画结束了');}} onExit={()=>{console.log('动画要开始了');}} classNames='f' unmountOnExit timeout={3000} in={this.state.flg}> <h1>React的动画</h1> </CSSTransition>
2- 列表动画
<h1>列表动画</h1> <TransitionGroup> {this.state.arr.map((item,i)=>{ return ( <CSSTransition key={item} classNames='f' timeout={1000} unmountOnExit> <li>{item} <button onClick={()=>this.del(i)}>移出</button></li> </CSSTransition> ) })} </TransitionGroup>
3- 组件库ant
1- 安装
npm i antd --save
2- 使用
1- 全部导入
---index.js
import 'antd/dist/antd.css'
2- 按需加载
2-1 手动按需加载
// 按需加载 import 'antd/es/button/style/index.css' import 'antd/es/breadcrumb/style/index.css'
2-2 借助插件自动按需加载
-
安装插件
npm i babel-plugin-import --save
-
修改.babelrc文件的插件配置
{ "presets": [ "react-app" ], "plugins": [ ["import", { "libraryName": "antd", "style": "css" }] ] }
-
修改config/webpack.config.js
-
需要npm run eject 导出配置文件
npm run eject git add . git commit -m 注释 npm run eject
-
在package.config.js修改 443行
babelrc: true, //443
-
package.json 删除多余的代码
babel:{ "presets": [ "react-app" ] }
-
-
启动项目
antd-mobile
1- 安装
npm i antd-mobile --save
2- 使用
1- 修改html
<!DOCTYPE html> <html> <head> <!-- set `maximum-scale` for some compatibility issues --> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script> <script> if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } if(!window.Promise) { document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>'); } </script> </head> <body></body> </html>
2- 全部导入
import 'antd-mobile/dist/antd-mobile.css';
3- 按需导入
如上