react
1.依赖上次更新的更新
this.setState(prevState => {
return {
count: prevState.count + 1
}
})
2.b避免重复更新
1.原始写法
shouldComponentUpdate(nextProps){
if(nextProps.data.body === this.props.data.body){
return false
}else{
return true
}
}
2.15.3后 浅比较(值类型有效)
class Comment extends PureComponent{
}
3.16.6后React.memo来完美实现react组件,让函数式组件也有PureComponent的功能
const Comment = React.memo(
function (props){
return (
<div>
<p>{props.body}</p>
</div>
)
}
)
//接收一个组件,返回一个全新的组件
3.高阶组件(本身为函数)
//接收一个组件,返回一个新组件(解决组件的复用)
//展示性组件
function Indexs(props){
return(
<div>
{props.stage} - {props.name}
</div>
)
}
//高阶组件
const Home = Comp =>{
//获取name
const name = '高阶组件'
return props => (
<Comp {...props} name={name}></Comp>
)
}
//使用
const NewHome = Home(Indexs)
export default class Hoc extends Component{
render(){
return(
<div>
<NewHome stage='React' />
</div>
)
}
}
可以改变生命周期的高阶组件
const MyHome = Comp =>{
//获取name
const name = '高阶组件'
return class extends Component(
conponentDidMount(){
console.log('这是带生命周期的高阶组件')
}
render(){
return <Comp {...this.props} name={name}></Comp>
}
)
}
高阶组件可以链式调用 const NewHome = Home(MyHome(Indexs))
4.装饰器(ES7)
1.依赖
npm install babel-plugin-transform-decorators-legacy -S
//配置
config.overnides.js
config = injectBabelPlugin(
config = injectBabelPlugin(
['@babel/plugin-proposal-decorators',{ legacy : true}],
config
)
return config;
)
2.使用
//装饰器 只能应于class组件
//注意 MyHome , Indexs 高阶组件要写作展示性组件上面
@MyHome
@Indexs
//展示性组件
class Indexs extends Component {
render(){
return (
<div>
{this.props} - {this.props.name}
</div>
)
}
}
//直接使用 Indexs 即可为高阶组件
5.组件复合
//Dialong 作为容器,不关心内容喝逻辑
function Dialog(props){
retrun <div style={{border: `1px solid ${props.color || 'red'}`}}>{props.children}</div>
}
//WelcomeDialog 通过复合提供内容
function WelcomeDialog(props){
return (
<Dialog {...props}>
<h1>欢迎光临</h1>
</Dialog>
)
}
//等同于vue的slot
//react 推荐写法
export default function(){
return <WelcomeDialog color= 'red'/>
}
children实际为任何JS
const APi = {
getUser(){
return { name : 'jerry' , age : 20}
}
}
function Fetch(props){
const user = APi[props.name]();
return props.childern(user)
}
export default function(){
return (
<Fetch name= 'getUser'>
{({name,age})=>{
<p>
{name} - {age}
</p>
}}
</Fetch>
)
}
过滤
function Fetch({children,type}){
return(
<div>
{React.Children.map(children,child =>{
if(child.typr !== type){
return;
}
retrun child
})}
</div>
)
}
//只显示p标签
export default function(){
return (
<Fetch type='p'>
<h1>react</h1>
<h2>react很不错呀</h1>
<h3>哈哈</h3>
<p>这是p</p>
</Fetch>
)
}
克隆
function RadioGroup(props){
return (
<div>
{React.Children.map(props.children,child =>{
// vdom 不可更改,需要克隆一个新的 才能去改
return React.cloneElement(child, {name: props.name})
}) }
</div>
)
}
function Radio({children,..rest}){
return (
<label>
<input type='radio' {...rest} />
{children}
</label>
)
}
export default function(){
return (
<RadioGroup name='mvvm'>
<Radio value='vue'>vue</Radio>
<Radio value='react'>react</Radio>
</RadioGroup>
)
}
6.Hook
1.单状态
import React,{ useState } from 'react'
export default function HookTest(){
const [count,setCount] = useState(0)
return (
<div>
<p>点击了{count}
<button onClick={() => setCount(count+1)}>点击了</button>
</div>
)
}
//使用
<HookTest></HookTest>
2.多状态
import React,{ useState } from 'react'
export default function HookTest(){
const [count,setCount] = useState(0)
const [age,setAge] = useState(20)
const [all,setAll] = useState([1,2,3])
return (
<div>
<p>点击了{count}
<button onClick={() => setCount(count+1)}>点击了</button>
</div>
)
}
//使用
<HookTest></HookTest>
7.副作用钩子 Effect Hook
import React,{ useState } from 'react'
export default function HookTest(){
const [count,setCount] = useState(0)
const [age,setAge] = useState(20)
const [all,setAll] = useState([1,2,3])
//副作用钩子会在每次渲染时都执行
/**
* 相当于componentDidMount,componentDidUpdate,componentUnmount
* 的一个综合体,可以拥有多个
*/
// 1. 只要业务发生变化就会执行
useEffect(()=>{
document.title = `你点击了${count}次 `
})
/**
* 如果今打算执行一次,可在第二个参数传入一个空数组
*
*/
// 2.只会在挂载是时候执行一次
useEffect(()=>{
document.title = `你点击了${count}次 `
},[])
// 3.只有count 发生变化了 才会执行
useEffect(()=>{
document.title = `你点击了${count}次 `
},[count])
return (
<div>
<p>点击了{count}
<button onClick={() => setCount(count+1)}>点击了</button>
</div>
)
}
//使用
<HookTest></HookTest>
8.自定义钩子
自定义钩子 是一个函数
function sueAge(){
const [ age, setAge ] = useState(0)
useEffect(() => {
setTimeout(() =>{
setAge(20)
},2000)
})
return age
}
import React,{ useState } from 'react'
export default function HookTest(){
const count= sueAge()
return (
<div>
<p>点击了{count}</p>
</div>
)
}
9.其他Hook
useContext,useReducer,useCallback,useMemo
10.上下文
隔代组件传值
import React from 'react'
//创建上下文
const MyConText = React.createContext()
const { Provider , Consumer} = MyConText
function Child(prop){
return (
<div>
Child :{prop.foo}
</div>
)
}
export default function ContextTest(){
return (
<div>
<Provider value={{foo: 'bar'}}>
<Consumer>
{value => <Child {...value}></Child>}
</Consumer>
</Provider>
</div>
)
}
2.Hook
import React,{ useContext } from 'react'
//创建上下文
const MyConText = React.createContext()
const { Provider , Consumer} = MyConText
function Child(prop){
const ctx = useContext(MyConText)
return (
<div>
Child :{ctx.foo}
</div>
)
}
export default function ContextTest(){
return (
<div>
<Provider value={{foo: 'bar'}}>
<Child></Child>
</Provider>
</div>
)
}
3.class
import React,{ useContext } from 'react'
//创建上下文
const MyConText = React.createContext()
const { Provider , Consumer} = MyConText
class Child extends Component{
static contextType = MyConText
render(){
return <div>Child : {this.context.foo}</div>
}
}
export default function ContextTest(){
return (
<div>
<Provider value={{foo: 'bar'}}>
<Child></Child>
</Provider>
</div>
)
}