dva+umi+antdを使用してページを構築する(3)

59618 ワード

dva+umi+antdを使用してページを構築する(3)
レイアウトができたらシステム全体のルーティングとそれに対応するルーティングコンポーネントの構築を開始することができるが,ルーティングを要求するページがTabsラベルページにある場合があり,各ラベルページをクリックして切り替えることができ,次にこのレイアウトの実現を検討する.
Tabsコンポーネント
  • Tabsコンポーネントを追加し、src/components/layoutにTabsを追加する.jsコンポーネントは、まず公式サイトでhttps://ant.design/components/tabs-cn/Tabsコンポーネントをコピーすると、次のようになります.
    import React from 'react'
    import { Tabs, Button } from 'antd';
    
    const TabPane = Tabs.TabPane;
    
    class Mytab extends React.Component {
      constructor(props) {
        super(props);
        this.newTabIndex = 0;
        const panes = [
          { title: 'Tab 1', content: 'Content of Tab Pane 1', key: '1' },
          { title: 'Tab 2', content: 'Content of Tab Pane 2', key: '2' },
        ];
        this.state = {
          activeKey: panes[0].key,
          panes,
        };
      }
    
      onChange = (activeKey) => {
        this.setState({ activeKey });
      }
    
      onEdit = (targetKey, action) => {
        this[action](targetKey);
      }
    
      add = () => {
        const panes = this.state.panes;
        const activeKey = `newTab${this.newTabIndex++}`;
        panes.push({ title: 'New Tab', content: 'New Tab Pane', key: activeKey });
        this.setState({ panes, activeKey });
      }
    
      remove = (targetKey) => {
        let activeKey = this.state.activeKey;
        let lastIndex;
        this.state.panes.forEach((pane, i) => {
          if (pane.key === targetKey) {
            lastIndex = i - 1;
          }
        });
        const panes = this.state.panes.filter(pane => pane.key !== targetKey);
        if (panes.length && activeKey === targetKey) {
          if (lastIndex >= 0) {
            activeKey = panes[lastIndex].key;
          } else {
            activeKey = panes[0].key;
          }
        }
        this.setState({ panes, activeKey });
      }
    
      render() {
        return (
          <div>
            <div style={{ marginBottom: 16 }}>
              <Button onClick={this.add}>ADD</Button>
            </div>
            <Tabs
              hideAdd
              onChange={this.onChange}
              activeKey={this.state.activeKey}
              type="editable-card"
              onEdit={this.onEdit}
            >
              {this.state.panes.map(pane => <TabPane tab={pane.title} key={pane.key}>{pane.content}</TabPane>)}
            </Tabs>
          </div>
        );
      }
    }
    export default Mytab
    
    で、src/layouts/indexに置き換えます.jsのContent rander関数は、
    return (
          <Layout>
            <MySider collapsed={collapsed}>
              <MyMenu {...menuProps}/>
            MySider>
            <Layout>
              <Header collapsed={collapsed} onCollapseChange={onCollapseChange}/>
              <MyTab>
                {this.props.children}
              MyTab>
            Layout>
          Layout>
        );
    
    ページにtabコンポーネントが表示され、
  • を正常に追加削除できます.
  • ステータスアップは、次にtabコンポーネントのステータスアップをdvaによって管理する必要があるので、tabコンポーネント
    import React from 'react'
    import {Tabs,Button} from 'antd';
    import PropTypes from "prop-types";
    
    const TabPane = Tabs.TabPane;
    
    class MyTab extends React.Component {
    
      onEdit = (targetKey, action) => {
        this[action](targetKey);
      }
    
      remove = (targetKey) => {
        const {onPaneRemove} = this.props
        onPaneRemove(targetKey)
      }
    
      render() {
        const {
          panes,
          activeKey,
          onPaneChange,
          onPaneAdd,
        } = this.props
        return (
          <div>
            <div style={{ marginBottom: 16 }}>
              <Button onClick={onPaneAdd}>ADD</Button>
            </div>
            <Tabs
              hideAdd
              onChange={onPaneChange.bind(this)}
              activeKey={activeKey}
              type="editable-card"
              onEdit={this.onEdit}
            >
              {panes.map(pane => <TabPane tab={pane.title} key={pane.key} closable={pane.closable}>
                {pane.content}
              </TabPane>)}
            </Tabs>
          </div>
        );
      }
    }
    
    MyTab.propTypes = {
      panes: PropTypes.array.isRequired,
      activeKey: PropTypes.string.isRequired,
      onPaneChange: PropTypes.func.isRequired,
    }
    export default MyTab
    
    
    を改造してsrc/layouts/indexを変更する.js
    import React from 'react'
    import {Layout} from 'antd';
    import Header from '../components/layout/Header'
    import MySider from '../components/layout/Sider'
    import MyMenu from '../components/layout/Menu'
    import MyTab from '../components/layout/Tabs'
    
    import {connect} from 'dva';
    
    class BasicLayout extends React.Component {
      onCollapseChange = collapsed => {
        this.props.dispatch({
          type: 'app/handleCollapseChange',
          payload: {collapsed},
        })
      }
    
      handelMenuClick = (element) => {
        //       
        this.props.history.push(element.item.props.url)
      }
    
      onPaneAdd = () => {
        //todo something
      }
    
      onPaneChange = () => {
        //todo something
      }
    
      onPaneRemove = () => {
        //todo something
      }
    
      render() {
        const {app, children} = this.props
        const {menus, theme, collapsed,panes,activeKey,} = app
        const {handelMenuClick, onCollapseChange,onPaneAdd,onPaneChange,onPaneRemove} = this
        const menuProps = {
          theme,
          menus,
          children,
          handelMenuClick,
          onCollapseChange,
        }
        const tapProps = {
          panes,
          children,
          activeKey,
          onPaneAdd,
          onPaneChange,
          onPaneRemove,
        }
    
        return (
          <Layout>
            <MySider collapsed={collapsed}>
              <MyMenu {...menuProps}/>
            </MySider>
            <Layout>
              <Header collapsed={collapsed} onCollapseChange={onCollapseChange}/>
              <MyTab {...tapProps}>
                {this.props.children}
              </MyTab>
            </Layout>
          </Layout>
        );
      }
    }
    
    export default connect((({app}) => ({app})))(BasicLayout)
    
    
    その後、src/models/appを変更する.js
    export default {
      namespace: 'app',
      state: {
        collapsed: false,
        activeKey: '1',
        panes: [
          {title: `dashboard`, content: '', key: '1', closable: false, url: '/dashboard'},
        ],
        theme: 'dark',
        menus: [{
          id: '1',
          name: 'dashboard',
          icon: 'dashboard',
          url: '/dashboard',
        }, {
          id: '2',
          name: '    ',
          icon: 'user',
          url: '1',
          children: [{
            id: '3',
            name: '    ',
            icon: 'user',
            url: '/user',
          },]
        }, {
          id: '3',
          name: '    ',
          icon: 'user',
          url: '1',
          children: [{
            id: '4',
            name: '    ',
            icon: 'user',
            url: '/user',
          },]
        }],
      },
      subscriptions: {},
      effects: {},
      reducers: {
        updateState(state, {payload}) {
          return {
            ...state,
            ...payload,
          }
        },
        handleCollapseChange(state, {payload}) {
          return {
            ...state,
            ...payload,
          }
        },
      },
    }
    
    
    は最後にsrc/layouts/indexを完了した.jsのいくつかの制御状態の関数
    onPaneAdd = () => {
        const {app, dispatch} = this.props
        const {panes,} = app
        let newPane = {title: 'new Tab', content: '', key: panes.length + '1',}
        let flag = false
        let newPanes = panes.map(item => {
          if (newPane.key === item.key) {
            flag = true
            return {...item, ...newPane}
          }
          return item
        })
        dispatch({
          type: 'app/updateState',
          payload: {
            panes: flag ? newPanes : [...newPanes, newPane],
            activeKey: newPane.key,
          },
        })
      }
    
      onPaneChange = targetKey => {
        const {dispatch,} = this.props
        dispatch({
          type: 'app/updateState',
          payload: {
            activeKey: targetKey
          },
        })
      }
    
      onPaneRemove = targetKey => {
        const {dispatch,} = this.props
        const payload = this._removeTap(targetKey)
        dispatch({
          type: 'app/updateState',
          payload: payload,
        })
      }
    
      _removeTap = (targetKey) => {
        const {panes, activeKey} = this.props.app
        let newActiveKey = activeKey
        let lastIndex;
        panes.forEach((pane, i) => {
          if (pane.key === targetKey) {
            lastIndex = i - 1;
          }
        });
        const newPanes = panes.filter(pane => pane.key !== targetKey);
        if (newPanes.length && activeKey === targetKey) {
          if (lastIndex >= 0) {
            newActiveKey = newPanes[lastIndex].key;
          } else {
            newActiveKey = newPanes[0].key;
          }
        }
        return {
          panes: newPanes,
          activeKey: newActiveKey
        }
      }
    
    はこれで追加と削除が可能になるが、メニューをクリックして追加し、このページを表示する必要があるので、src/layouts/indexをもう少し改造する.jsの関数は、Tabコンポーネントの追加ボタンをindexから削除する.js
    //      
    handelMenuClick = element => {
        let newPane = {title: element.item.props.name, content: '', key: element.key, url: element.item.props.url}
        this.onPaneAdd(newPane)
      }
    //   tab
      onPaneAdd = (newPane) => {
        const {app, dispatch, history,} = this.props
        const {panes,} = app
        let flag = false
        //       
        history.push(newPane.url)
        setTimeout(()=>{
          newPane.content = this.props.children
          let newPanes = panes.map(item => {
            if (newPane.key === item.key) {
              flag = true
              return {...item, ...newPane}
            }
            return item
          })
          dispatch({
            type: 'app/updateState',
            payload: {
              panes: flag ? newPanes : [...newPanes, newPane],
              activeKey: newPane.key,
            },
          })
        },100)
      }
    
    Tabs.js
    //        tab
      componentWillMount(){
        const {panes, onPaneAdd,} = this.props
        if (panes.length === 1) {
          const pane = panes[0]
          onPaneAdd(pane)
        }
      }
    
    これによりtabの追加と削除を実現できる:
  • 参照コード:https://github.com/enusune/myapp