在可复用组件而不是可复用函数时谈过react的组件化。当时正在忙于微信电影票的重构,写了大量拼凑的模板函数。
在文章写之后就对微信电影票选座页代码中拼凑的模板函数进行了复写。以组件的形式展示。但因为一些历史原因,中心座位图的部分代码没办法改动。这次终于下定决心把中心选座区的代码重新了一遍,对组件化的理解又加深了一步。加上通过组件生命周期的灵活设置,避免了重复渲染,提高了性能。
组件化
先来看一下使用拼凑的模板函数来写出的可复用函数
export default class Home extends Page {
constructor(...args) {
super(...args)
this.state = {
movieName: '奇异博士',
movieTime: '12:40'
}
}
renderMovie(movieName) {
//...
return (
<div>{movieName}</div>
)
}
renderMovieTime(movieTime) {
return (
<div>{movieTime}</div>
}
changeMovieName() {
this.setState = {
movieName: '蜡笔小新'
}
changeMovieTime() {
this.setState = {
movieTime: '12:50'
}
}
render() {
let { movieName, movieTime } = this.state
return(
<div onClick={this.changeMovieName.bind(this)}>...</div>
<div>{renderMovie(this, movieName)}</div>
<div>{renderMovieTime(this, movieTime)}</div>
<div onClick={this.changeMovieTime.bind(this)}>...</div>
)
}
}
好像也没什么问题,当时只是觉得这种写法不太符合组件化的思想,只是把以前JQuery的想法直接拿来写react
但在经历选座页组件化复写之后,总结出了这样写实际的弊端:
- 拼凑的模板函数没有对传入的参数进行校验,后续修改与维护不方便。
- 拼凑的模板函数只能写到该组件内部,很难被其他页面引用。
- 只要props或者state改变,拼凑的模板函数就会重新渲染,多余的渲染必然造成性能的下降
知道了拼凑的模板函数弊端之后,现在我们把上面的代码转化成组件的形式
//home.js
import Movie from './Movie'
import MovieTime from './MovieTime'
export default class Home extends React.Component {
constructor(...args) {
super(...args)
this.state = {
movieName: '奇异博士',
movieTime: '12:40'
}
}
changeMovieName() {
this.setState = {
movieName: '蜡笔小新'
}
changeMovieTime() {
this.setState = {
movieTime: '12:50'
}
}
render() {
let { movieName, movieTime } = this.state
return(
<div onClick={this.changeMovieName.bind(this)}>...</div>
<Movie movieName={movieName} />
<MovieTime movieTime={movieTime} />
<div onClick={this.changeMovieTime.bind(this)}>...</div>
)
}
}
//Movie.js
class Movie extends React.Component {
shouldComponentUpdate(nextProps) {
const { movieName } = this.props
return movieName === nextProps.movieName
}
render() {
const { movieName } = this.props
return(
<div>{movieName}</div>
}
}
export default props => {
const { movieName} = props
return (
<Movie movieName={movieName} />
)
}
Movie.propTypes = {
movieName: React.PropTypes.string.isRequired,
}
//MovieTime.js
class MovieTime extends React.Component {
shouldComponentUpdate(nextProps) {
const { movieTime } = this.props
return movieTime === nextProps.movieTime
}
render() {
const { movieTime } = this.props
return(
<div>{movieTime}</div>
}
}
export default props => {
const { movieTime} = props
return (
<MovieTime movieTime={movieTime} />
)
}
MovieTime.propTypes = {
movieTime: React.PropTypes.string.isRequired,
}
通过propType进行组件参数校验。通过shouldComponentUpdate控制渲染性能,避免重复渲染。后续Movie和MovieTime组件也能够被其他页面很方便的调用。
这就是react组件的正确使用方法。关于通过propType来规范组件的props的类型,后续再专门写篇文章讲吧~