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值生成
PureComponent的state和props前后对比
由于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
神奇:高阶组件多重装饰之后,只要引入,哪怕不挂在到页面上,都会执行装饰器中的函数
React复合组件写法
1、props.children作为一个属性
// 复合组件(相当于vue中的slot插槽)
import React from 'react'
function Dialog(props){
return {props.children}
}
function WelcomeDialog(props){
return
}
export default function(){
return
}
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增加/修改属性
// 复合组件(相当于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属性
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代码书写过程中,起别名直接用:
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(没有值)
解构赋值和导入起别名区别
解构的时候起别名用:
导入的时候起别名:
1、export导出
2、export导入:
3、import导入: