in src/ui/widget/Collapsible.tsx [101:148]
static getDerivedStateFromProps(nextProps:Prop, prevState:State): State {
const self = prevState.self;
// open状态不变,直接返回。这个判断是要的,否则初始隐藏的元素高度获得不了,因为下面的代码会把maxHeight设置为0
if(self.state.css.visibility == "hidden" && !nextProps.open || self.state.css.visibility == "visible" && nextProps.open){
return null;
}
if(_.isNil(nextProps.ms)) { // 没有动画
return Collapsible.genNextState(self, nextProps.open, false);
}
let nextState = null;
if(prevState.css.visibility === "visible" && !nextProps.open) { // 折叠
// 折叠前,重新获取元素高度,虽然componentDidMount里记录过,但渲染过以后,万一元素高度又变了呢?
const heightNow = prevState.self.div.offsetHeight;
nextState = Collapsible.genNextState(self, true, true); // maxHeight设置为元素被折叠前的高度,以启动动画
clearTimeout(self.action)
self.action = setTimeout(()=>{
self.setState(Collapsible.genNextState(self, false, true)); // maxHeight设置为0,以完成动画
self.action =setTimeout(()=>{
self.setState(Collapsible.genNextState(self, false, false)); // 去掉maxHeight,这样元素高度仍然是可变的
}, self.props.ms)
})
// 计入height,展开时用
self.height = _.max([heightNow, self.height]);
} else if(prevState.css.visibility === "hidden" && nextProps.open) { // 展开
// 原来没有maxHeight,需要给个初始的,等下再改掉。因为maxHeight必须有变化,才能触发动画
nextState = Collapsible.genNextState(self, false, true); // maxHeight设置为0,以启动动画
clearTimeout(self.action)
self.action = setTimeout(()=>{
self.setState(Collapsible.genNextState(self, true, true)); // maxHeight设置为折叠前的高度,以完成动画
self.action = setTimeout(()=>{
self.setState(Collapsible.genNextState(self, true, false)); // 去掉maxHeight/display,这样元素高度仍然是可变的
}, self.props.ms)
})
}
// else { // 状态不变,不用动
// }
return nextState;
}