2019-11-02React高阶组件学习踩坑

react+mobx+antd按需加载 出现Support for the experimental syntax 'decorators-legacy' isn't currently enabled

baidu上面的说法大多是在 项目的package.json 中添加decorators-legacy

因为引入了antd的按需加载 所以只需要在config-overrides.js中添加addDecoratorsLegacy()

const { override, fixBabelImports, addDecoratorsLegacy } = require('customize-cra');
module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  addDecoratorsLegacy(),
);

对象的key值生成

image.png

PureComponent的state和props前后对比

2019-11-02React高阶组件学习踩坑_第1张图片
image.png

2019-11-02React高阶组件学习踩坑_第2张图片
image.png

由于shouldComponentUpdate上第一个校验规则是前后的值完全相等(值类型值相等,引用类型地址相等),如果引用类型前后的值相等但是地址不等,仍然会认为是不等的,继续更新
所以,使用的时候props和state避免传入与引用类型

React高阶组件书写模式

1、普通生成

// 高阶组件
import React from 'react'

function Kaikeba(props){
  return 
{props.stage}---{props.name}
} const withKaikeba = Comp => { const name="高阶组件" return props => } const NewKaikeba = withKaikeba(Kaikeba) class Rong extends React.Component{ constructor(props){ super(props) this.state={ stage:"React" } } render(){ return } } export default Rong

2、 高阶组件中改写原组件生命周期

const withKaikeba = Comp => {
  const name="高阶组件"
  return class extends React.Component{
    componentDidMount(){
      console.log("do something")
    }
    render(){
      return 
    }
  }
}

3、不止一个高阶组件进行强化

const withLog = Comp => {
  console.log(Comp.name+"渲染了");
  return props => 
}
- // const NewKaikeba = withKaikeba(Kaikeba)
+ const NewKaikeba = withLog(withKaikeba(withLog(Kaikeba)))

4、高阶组件简洁写法

- const NewKaikeba = withLog(withKaikeba(withLog(Kaikeba)))


import React from 'react'

const withKaikeba = Comp => {
  const name="高阶组件"
  return class extends React.Component{
    componentDidMount(){
      console.log("do something")
    }
    render(){
      return 
    }
  }
}

const withLog = Comp => {
  console.log(Comp.name+"渲染了");
  return props => 
}

@withLog
@withKaikeba
@withLog
class Kaikeba extends React.Component{
  render(){
    return 
{this.props.stage}---{this.props.name}
} } // const NewKaikeba = withKaikeba(Kaikeba) // const NewKaikeba = withLog(withKaikeba(withLog(Kaikeba))) class Rong extends React.Component{ constructor(props){ super(props) this.state={ stage:"React" } } render(){ return } } export default Rong

神奇:高阶组件多重装饰之后,只要引入,哪怕不挂在到页面上,都会执行装饰器中的函数


2019-11-02React高阶组件学习踩坑_第3张图片
image.png

2019-11-02React高阶组件学习踩坑_第4张图片
image.png

React复合组件写法

1、props.children作为一个属性
// 复合组件(相当于vue中的slot插槽)
import React from 'react'

function Dialog(props){
  return 
{props.children}
} function WelcomeDialog(props){ return

欢迎光临

下午好

} export default function(){ return }
2019-11-02React高阶组件学习踩坑_第5张图片
image.png
2、props.footer添加一个具名插槽
const footer = 

return 

  
{props.children}
{props.footer}
3、props.children作为一个函数--->作用域插槽)
// 作用域插槽
const Api = {
  getUser(){
    return { name: "jerry", age: 18 }
  }
}

function Fetcher(props){
  const user = Api[props.name]()
  return props.children(user)
}

      
        {({name, age}) => (
          

姓名:{name}

年龄:{age}

)}
4、props.children增加/修改属性
2019-11-02React高阶组件学习踩坑_第6张图片
image.png
// 复合组件(相当于vue中的slot插槽)
import React from 'react'
import { Button } from 'antd'

function Dialog(props){
  return (
  
{props.children}
{props.footer}
) } function WelcomeDialog(props){ return

欢迎光临

下午好

} // 作用域插槽 const Api = { getUser(){ return { name: "jerry", age: 18 } } } function Fetcher(props){ const user = Api[props.name]() return props.children(user) } function Filetr({ children, type }) { { React.Children.forEach(children, child => { console.log(child); // child.props.children="都给我统一" }) } return (
{/* { React.Children.forEach( children, child => { console.log(React.Children); if(child.type === type){ return; }else{ return child } } ) } */} { children }
) } function RadioGroup(props){ return (
{ React.Children.map( props.children, child => { return React.cloneElement(child, { name: props.name }) } ) }
); } function Radio({ children, ...rest }){ return ( ); } export default function(){ // const footer = // return return (
{/* {({name, age}) => (

姓名:{name}

年龄:{age}

)}

这是个p

这是h1

这又是个p

这又是个h1

*/} vue react angular
); }

此时,子元素里面除了value外,也多了name属性


image.png

ReactHook

useEffect副作用

是一个函数,相当于渲染过程中的三个生命周期,第一个参数是一函数(需要执行的事件),第二个参数是与此相关的状态(空:所有状态改变都执行;[]:所有状态改变都不执行;['count']:只有count改变才执行)

自定义钩子
  // 自定义钩子
  function useAge(){
    const [ age, setAge ] = useState()
    useEffect(() => {
      setTimeout(() => {
        setAge(21)
      },2000)
    })
    return age
  }
  const age = useAge()

年龄是{age ? age : "loading..."}

Context上下文使用(使用场景:隔代传参)

import React, { useContext } from 'react'
// 创建上下文
const MyContext = React.createContext()
const { Provider, Consumer } = MyContext

function Child(props) {
  return (
    
{ props.foo }
) } function Child2(props){ const ctx = useContext(MyContext) return (
{ctx.foo}
); } class Child3 extends React.Component { static contextType = MyContext render(){ return (
{ this.context.foo }
); } } export default function ContextTest() { return (
{/* 隔代传参第一种方式:Consumer */} { value => } {/* 隔代传参第二种方式:钩子 */} {/* 隔代传参第三种方式:class */}
) }

React代码书写过程中,起别名直接用:

2019-11-02React高阶组件学习踩坑_第7张图片
React中起别名

generator初始化函数与.next()传值时机

function* figer(num){
  let b = "这是一个b"
  setTimeout(()=>{
    console.log("异步函数执行");
    
    // return "return 一个 value"
    
  })
  console.log(b);
  
  let a = yield num;
  console.log(b);
  
  console.log(a);
  yield num + 1
  
}

let it = figer(2)
console.log(it);
// console.log(it.next()); // { value: undefined, done: false }
console.log(it.next('给a传值'));
console.log(it.next());
console.log(it.next());

// generator函数接收函数外面的值在初始化阶段调用时传递
// generator函数的第一个.next()调用,只执行第一个yield函数之前的非异步函数(未yield的异步函数在最后)
// 并执行这第一个yield后面的表达式,并返回一个{value:xxx,done:Boolean}
// generator的第二个.next()调用,执行第二个yield函数之前的非异步函数
// 并执行当前的yield函数,并将此.next()传入的参数赋值给第一个yield函数之前的表达式接收值

// 如果在第二个.next()执行的时候不传入值,则第一个yield表达式之前的接收值为undefined(没有值)

解构赋值和导入起别名区别

解构的时候起别名用:
2019-11-02React高阶组件学习踩坑_第8张图片
image.png
导入的时候起别名:

1、export导出


2019-11-02React高阶组件学习踩坑_第9张图片
image.png

2、export导入:


2019-11-02React高阶组件学习踩坑_第10张图片
具名导入所有模块起别名

3、import导入:
2019-11-02React高阶组件学习踩坑_第11张图片
具名改别名

你可能感兴趣的:(2019-11-02React高阶组件学习踩坑)