antd 提供 Layout, Header, Sider, Content, Footer 組件用於劃定頁面布局。實現上,側邊欄 Sider 組件比較特殊,將在第一部分加以介紹;其餘組件均將在第一部分加以介紹。

1. Layout

布局容器 Layout, 頂部布局 Header, 內容部分 Content, 底部布局 Footer 在實現上大體相當:都是通過 generator(props) = BasicComponent => Adapter 創建高階組件 Adapter,再由該高階組件將 props.prefixCls 注入到 BasicComponent 中。

作為 Layout 組件的 BasicComponent,BasicLayout 組件以 state.siders 記錄側邊欄的 id,並允許在子組件中使用 context.siderHook 添加或移除側邊欄,其意義是觸發 BasicLayout 組件重繪並判斷是否需要添加 .ant-layout-has-sider 樣式類。作為 Header, Content, Footer 組件的 BasicComponent,Basic 組件只用於拼接 props.prefixCls, props.className,以構成新的樣式類。

Header, Sider, Content, Footer 組件只能作為 Layout 的子組件這一特徵,由 less 文件約定,即如果當上述組件不作為 Layout 的子組件時,其樣式將得不到正常展示。

2. Sider

側邊欄 Sider 組件用於設定布局,其內容可由 Menu 組件 繪製。在 componentDidMount, componentWillUnmount 生命周期中,側邊欄組件也將通過 context.siderHook.addSider, context.siderHook.removeSider 方法,以添加或移除 Layout 容器中記錄的側邊欄 id。側邊欄組件既可以根據摺疊狀態切換按鈕展開或摺疊(通過 props.collapsible 或 props.collapsedWidth = 0 開啟);也可以根據屏幕尺寸響應式展開或摺疊(通過 props.breakpoint 屬性開啟),其實現藉助 window.matchMedia 方法。子組件可通過 context.siderCollapsed 獲得側邊欄的展開和摺疊狀態。以下是響應式展開或摺疊功能的實現。

// matchMedia polyfill for
// https://github.com/WickyNilliams/enquire.js/issues/82
if (typeof window !== undefined) {
const matchMediaPolyfill = (mediaQuery: string) => {
return {
media: mediaQuery,
matches: false,
addListener() {
},
removeListener() {
},
};
};
window.matchMedia = window.matchMedia || matchMediaPolyfill;
}

class Sider extends React.Component<SiderProps, SiderState> {
constructor(props: SiderProps) {
// ...

let matchMedia;
if (typeof window !== undefined) {
matchMedia = window.matchMedia;
}
if (matchMedia && props.breakpoint && props.breakpoint in dimensionMap) {
this.mql = matchMedia(`(max-width: ${dimensionMap[props.breakpoint]})`);
}
}

componentDidMount() {
if (this.mql) {
this.mql.addListener(this.responsiveHandler);
this.responsiveHandler(this.mql);
}

// ...
}

responsiveHandler = (mql: MediaQueryListEvent | MediaQueryList) => {
this.setState({ below: mql.matches });
const { onBreakpoint } = this.props;
if (onBreakpoint) {
onBreakpoint(mql.matches);
}
if (this.state.collapsed !== mql.matches) {
this.setCollapsed(mql.matches, responsive);
}
}

setCollapsed = (collapsed: boolean, type: CollapseType) => {
if (!(collapsed in this.props)) {
this.setState({
collapsed,
});
}
const { onCollapse } = this.props;
if (onCollapse) {
onCollapse(collapsed, type);
}
}
}

側邊欄組件的斷點 props.breakpoint 包含五種可能:xs 為 480px;sm 為 576px;md 為 768px;lg 為 992px;xl 為 1200px;xxl 為 1600px。當設置了 props.breakpoint 時,就能實現響應式展開與摺疊功能。

當 props.collapsedWidth 設置為 0,摺疊狀態切換按鈕為 bars 類型。默認的摺疊狀態切換按鈕為 left 或 right 類型。此外,可以使用 props.trigger 設置自定義摺疊狀態切換按鈕。

側邊欄的主題樣式通過設置樣式類實現,如 ant-layout-sider-light。

側邊欄組件使用 react-lifecycles-compat 庫封裝,以在低版本的 react 中書寫 static getDerivedStateFromProps, getSnapshotBeforeUpdate 生命周期方法。


推薦閱讀:
相关文章