gmfe / Think

观麦前端团队的官方博客
68 stars 3 forks source link

Collapse 引发的思考 #28

Open liyatang opened 6 years ago

liyatang commented 6 years ago

Collapse 点击展开收起,一个很简单的功能。然而在获取 Collapse children ref 的时候出了点问题。

一般写法。使用 display 控制子元素的显示。

class Collapse extends React.Component {
    render() {
        const {open} = this.props;
        return (
            <div style={{display: open ? 'block': 'none'}}>
                {children}
            </div>
        );
    }
}

class Demo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            open: false
        };
    }
    componentDidMount(){
        console.log(this.refSome); // log some
    }
    render(){
        return (
            <div>
                <button onClick={() => this.setState({open: !this.state.open})}>open</button>
                <Collapse open={this.state.open}>
                    <Some ref={ref => this.refSome = ref}/>
                </Collapse>
            </div>
        );
    }
}

把 Collapse 改下

class Collapse extends React.Component {
    render() {
        const {open} = this.props;
        return (
            <div>
                {open && children}
            </div>
        );
    }
}

这样会获取不到 this.refSome ,因为 Some 还没有 render。所以如果 Collapse 采用是否渲染子节点的方法,就要多加留意。

解决方案当然是有,要么 Collapse children 单独一个组件,关于这个组件的逻辑都在组件内做。 要么在获取 this.refSome 的地方加判断逻辑。要么组件文档注明风险。

然而调用方是无感知的,也即问题随时可能会发生,随时去获取 this.refSome。类似的组件可能还有 Tab、Dialog 等。

总结:1 少用 children 不 render 的情况 2 组件拆细(倾向)