vue:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
react-hooks:
用useEffect
mounted
beforeDestroy
updated
import React, { useEffect, useState } from 'react'
// mounted
useEffect(()=> {
document.title = count
}, [])
// mounted 和 beforeDestroy 通常一起使用
useEffect(()=> {
notification.open({
message: '欢迎使用后台管理平台',
duration: null,
description: '账号 admin(管理员) 其他(游客) 密码随意'
})
return () => {
// 类似于 componentWillUnMount beforeDestroy
notification.destroy()
timer && clearTimeout(timer)
}
}, [])
// updated 根据props.location,每次更新都触发逻辑处理
useEffect(() => {
let { pathname } = props.location
setOpenKeys(getOpenKeys(pathname))
setSelectedKeys([pathname])
}, [props.location])
vue:
<template>
<div>
<Menu
mode='inline'
theme='dark'
:openKeys="openKeys"
:selectedKeys="selectedKeys"
@click="({ key }) => this.setSelectedKeys([key])"
:onOpenChange="onOpenChange">
<div v-for="item in props.menu">
<div v-if="item.subs && item.subs.length > 0">
123
div>
div>
Menu>
div>
template>
react-hooks:
return (
<Menu
mode='inline'
theme='dark'
openKeys={openKeys}
selectedKeys={selectedKeys}
onClick={({ key }) => setSelectedKeys([key])}
onOpenChange={onOpenChange}>
{
props.menu &&
props.menu.map(item => {
return item.subs && item.subs.length > 0 ? renderSubMenu(item) : renderMenuItem(item)
})
}
</Menu>
)
// vue
export default {
data() {
return {
openKeys: [],
selectedKeys: []
}
}
}
// react-hooks
import React, { useEffect, useState } from 'react'
const CustomMenu = (props) => {
const [openKeys, setOpenKeys] = useState([])
const [selectedKeys, setSelectedKeys] = useState([])
return (
)
}
// vue
export default {
props: {
location: {
type: String
},
menu: {
type: Array,
required: true
}
}
}
// react-hooks
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
const CustomMenu = (props) => {
}
CustomMenu.propTypes = {
menu: PropTypes.array.isRequired
}
import React from 'react'
import PropTypes from 'prop-types'
import { Breadcrumb } from 'antd'
import { Link } from 'react-router-dom'
const CustomBreadcrumb = props => (
<Breadcrumb style={{ marginBottom: 16 }}>
<Breadcrumb.Item>
<Link to='/index'>首页</Link>
</Breadcrumb.Item>
{
props.arr &&
props.arr.map(res => {
if (typeof res === 'object') {
return (
<Breadcrumb.Item key={res.path}>
<Link to={res.path}>{res.title}</Link>
</Breadcrumb.Item>
)
} else {
return <Breadcrumb.Item key={res}>{res}</Breadcrumb.Item>
}
})
}
</Breadcrumb>
)
CustomBreadcrumb.propTypes = {
arr: PropTypes.array.isRequired
}
function shouldRender(nextProps, prevProps) {
if (nextProps.arr.join() === prevProps.arr.join()) {
return true
}
return false
}
export default React.memo(CustomBreadcrumb, shouldRender)
// PureComponent不同的是,React.memo()是一个高阶组件,用于函数组件,通过对前后props进行浅比较,如果前后props不一致,该组件将重新渲染,反之,不进行渲染,使用缓存中的组件
假设此代码出现在 React Hook 组件中, 在每次 render 的情况下
ComponentA 中的 函数 a 会被创建多少次?
ComponentB 中的 匿名函数 () => {} 会被创建多少次?
选项:
a. 1 & 1
b. 1 & c 变化时才会重新创建
const ComponentA = () => {
const a = () => {}
return <button onClick={a}>A</button>
}
const ComponentB = () => {
const b = useCallback(() => {}, [c])
return <button onClick={b}>B</button>
}
react性能优化参考
react性能优化参考
// react-loadable 第三方库 已停止维护,性能略差
export default function AsyncLoad(importFn) {
return Loadable({
loader : importFn,
loading : Loading
});
}
// React.lazy + React.Suspense 版本迭代,官方方案,不支持ssr
export default function AsyncLoad(importFn) {
const AsyncLoadComponent = React.lazy(importFn);
return (props) => (
<React.Suspense fallback={<Loading />}>
<AsyncLoadComponent {...props} />
</React.Suspense>
)