函数组件
父组件:Vote.jsx
import React, { useState, useCallback } from 'react'
import VoteMain from './VoteMain'
import VoteFooter from './VoteFooter'
import './Vote.less'
const Vote = function Vote() {
let [supNum, setSupNum] = useState(10),
[oppNum, setOppNum] = useState(5)
const change = useCallback(
(type) => {
if (type === 'sup') {
setSupNum(supNum + 1)
return
}
setOppNum(oppNum + 1)
},
[supNum, oppNum]
)
return (
<div className="vote-box">
<header className="header">
<h2 className="title">React真的很不错!!</h2>
<span className="num">{supNum + oppNum}人</span>
</header>
<VoteMain supNum={supNum} oppNum={oppNum} />
<VoteFooter change={change} />
</div>
)
}
export default Vote
子组件1:VoteMain.jsx
import React, { memo, useMemo } from 'react'
import PropTypes from 'prop-types'
const VoteMain = function VoteMain(props) {
let { supNum, oppNum } = props
let ratio = useMemo(() => {
let total = supNum + oppNum
return total > 0 ? ((supNum / total) * 100).toFixed(2) + '%' : '--'
}, [supNum, oppNum])
return (
<div className="main">
<p>支持人数:{supNum}人</p>
<p>反对人数:{oppNum}人</p>
<p>支持比率:{ratio}</p>
</div>
)
}
// 属性规则校验
VoteMain.defaultProps = {
supNum: 0,
oppNum: 0,
}
VoteMain.propTypes = {
supNum: PropTypes.number,
oppNum: PropTypes.number,
}
export default memo(VoteMain)
子组件2:VoteMain.jsx
import React, { memo } from 'react'
import PropTypes from 'prop-types'
const VoteFooter = function VoteFooter(props) {
let { change } = props
return (
<div className="footer">
<button onClick={change.bind(null, 'sup')}>支持</button>
<button onClick={change.bind(null, 'sup')}>反对</button>
</div>
)
}
// 属性规则校验
VoteFooter.propTypes = {
change: PropTypes.func.isRequired,
}
export default memo(VoteFooter)
优化:useCallback memo useMemo
类组件
父组件:Vote.jsx
import React from 'react'
import VoteMain from './VoteMain'
import VoteFooter from './VoteFooter'
import './Vote.less'
class Vote extends React.Component {
// 定义状态
state = {
supNum: 10,
oppNum: 5,
}
// 修改状态的方法:箭头函数可以保证方法中的this永远是父组件的实例
change = (type) => {
let { supNum, oppNum } = this.state
if (type === 'sup') {
this.setState({ supNum: supNum + 1 })
return
}
this.setState({ oppNum: oppNum + 1 })
}
render() {
let { supNum, oppNum } = this.state
return (
<div className="vote-box">
<header className="header">
<h2 className="title">React真的很不错!!</h2>
<span className="num">{supNum + oppNum}人</span>
</header>
<VoteMain supNum={supNum} oppNum={oppNum} />
<VoteFooter change={this.change} />
</div>
)
}
}
export default Vote
子组件1:VoteMain.jsx
import React from 'react'
import PropTypes from 'prop-types'
class VoteMain extends React.PureComponent {
/* 属性规则校验 */
static defaultProps = {
supNum: 0,
oppNum: 0,
}
static propTypes = {
supNum: PropTypes.number,
oppNum: PropTypes.number,
}
render() {
let { supNum, oppNum } = this.props
let ratio = '--',
total = supNum + oppNum
if (total > 0) ratio = ((supNum / total) * 100).toFixed(2) + '%'
return (
<div className="main">
<p>支持人数:{supNum}人</p>
<p>反对人数:{oppNum}人</p>
<p>支持比率:{ratio}</p>
</div>
)
}
}
export default VoteMain
子组件2:VoteMain.jsx
import React from 'react'
import PropTypes from 'prop-types'
class VoteFooter extends React.PureComponent {
/* 属性规则校验 */
static propTypes = {
change: PropTypes.func.isRequired,
}
render() {
let { change } = this.props
return (
<div className="footer">
<button onClick={change.bind(null, 'sup')}>支持</button>
<button onClick={change.bind(null, 'opp')}>反对</button>
</div>
)
}
}
export default VoteFooter
优化:pure component 减少不必要的更新