最近在做性能优化。基于 shouldComponentUpdate 来做比较。对于数据来说可以很容易比较(用了immutable)。
然而对于某些function来说怎么处理呢?
要求:能够动态传参v
假设有伪代码
class A extends React.Component{
constructor(props) {
super(props);
}
handleB(value){
console.log(value);
}
render(){
return <div>
{[1,2,3].map(v => <B onCallback={this.handleB.bind(this, v)} />)}
</div>
}
}
class B extends React.Component {
shouldComponentUpdate(nextProps){
const thisProps = this.props;
// ....省略
if(thisProps.onCallback === nextProps.onCallback){
return false;
}
return true;
}
render(){
return ....省略;
}
}
补充: 感谢大家,最终用了如下方案
class A extends React.Component{
constructor(props) {
super(props);
this.handleB = ::this.bindB;
}
handleB(event){
// 有了索引,就可以查到原数据了
console.log(event.currentTarget.dataset.index);
}
render(){
return <div>
{[1,2,3].map((v, i) => <B data-index={i} onCallback={this.handleB} />)}
</div>
}
}
我们先来看这么几个问题
如果props
是一个函数,能否用immutable
那套比较reference
的方式来判断
答案是:能。因为函数在javascript
里是一等公民,所谓一等公民就是可以被赋值给变量;而且函数本身也是一种特殊的Object
,当然可以通过reference
来比较,思路没有错
动态传參
map
函数在每次迭代时,就会自动调用callback
,并传入参数currentValue
、index
、array
,如下图:
所以动态穿參从来不是问题
bind
的问题
你在A
里的this.handleB.bind(this, v)
确实有一点点小问题,因为bind
会返回一个新的函数,这将导致你的if(thisProps.onCallback === nextProps.onCallback){
永远不成立,无论A
的哪个状态发生变化,bind
都会生成一个新的handleB
,那thisProps.onCallback === nextProps.onCallback
结果就是false
,即便对你来说根本没改过handleB
。
修正:
不好意思,之前关于v
这个部分看得不够仔细,重新看了一下,我是这么理解的:
既然你要里列表形式展示B
组件,那参照官方dynamic-children的写法,给组件增加一个key
属性,然后在组件B
内部通过key
属性,在B
组件内部调用onCallback
的时候,把key
的值带回给A
组件传入的函数才是可取之道。
所以A
需要这么调整下:
class A extends React.Component{
constructor(props) {
super(props);
//构造实例时绑定一次就好了
this.handleB = this.handleB.bind(this);
}
handleB(value){
console.log(value);
}
render(){
//下面用的就是同一个handleB函数
return <div>
{[1,2,3].map(v => <B key={v} onCallback={this.handleB} />)}
</div>
}
}
B
做如下调整:
class B extends React.Component {
shouldComponentUpdate(nextProps){
const thisProps = this.props;
// ....省略
if(thisProps.onCallback === nextProps.onCallback){
return false;
}
return true;
}
test(){
//假设这个test方法就是B里处理onCallback的地方,可以这么写:
this.props.onCallback(this.props.key);
}
render(){
return ....省略;
}
}
我太久不写
react
了,语法可能不太对,但思路是对的。鉴于你自己会写react
,语法如果有问题,自行调整吧
用 data-
来存参数
class Demo extends Component {
constructor(props) {
super(props);
this.clickHandler = this.clickHandler.bind(this);
}
render() {
const arr = [0, 1, 2];
return (
<div>
{
arr.map(i => (
<button
key={i}
data-index={i}
onClick={this.clickHandler}
/>
))
}
</div>
)
}
clickHandler(e) {
const index = e.currentTarget.dataset.index;
}
}