美文网首页技术杂谈
仿饿了么H5项目-React+antd-mobile实战(二)-

仿饿了么H5项目-React+antd-mobile实战(二)-

作者: aimmarc | 来源:发表于2019-10-31 14:47 被阅读0次

    搭建项目

    使用create-react-app创建一个新的react项目。

    npx create-react-app my-app
    cd my-app
    npm start
    

    如需使用typescript作为动态类型检测,则直接使用以下命令创建项目(笔者默认使用typescript):

    npx create-react-app my-app --typescript
    

    如果你想在现有项目添加typescript支持,请参考https://react.docschina.org/docs/static-type-checking.html

    安装ant-design-mobile:

    npm install ant-design-mobile --save
    

    安装react-router-dom:

    npm install react-router-dom --save
    

    安装redux、react-redux、redux-thunk:

    npm install redux react-redux redux-thunk --save
    

    配置路由

    在src文件夹新建layout、pages两个文件夹。layout文件夹下新建MainLayout.tsx文件,pages下新建Home、Order、My三个文件夹,在三个文件夹内分别新建一个index.tsx文件。

    |-src
        |-layout
            |-MainLayout.tsx
        |-pages
            |-Home
                |-index.tsx
            |-Order
                |-index.tsx
            |-My
                |-index.tsx
    

    给pages下面的三个文件夹分别添加如下代码:

    import React from 'react';
    
    const Home:React.FC = (props: any) => {
    
        return (
            <div>
                点餐
            </div>
        )
    };
    
    export default Home;
    
    import React from 'react';
    
    const Order:React.FC = (props: any) => {
    
        return (
            <div>
                订单
            </div>
        )
    };
    
    export default Order;
    
    import React from 'react';
    
    const My:React.FC = (props: any) => {
    
        return (
            <div>
                我的
            </div>
        )
    };
    
    export default My;
    
    

    在MainLayout.tsx中添加如下代码:

    import React from 'react';
    
    interface IProps {
        history: any;
        location: any;
    }
    
    interface IState {
        collapsed: Boolean;
        activeIndex: number;
    }
    
    export default class MainLayout extends React.Component<IProps, IState> {
        render() {
            return (
                <div className='main-layout'>
                    <div className='page-wrapper'>
                        {this.props.children}
                    </div>
                </div>
            );
        }
    }
    

    在src新建routes文件夹。在routes文件夹内新建两个文件,分别为index.tsx、children.tsx:

    |-src
        |-routes
            |-index.tsx
            |-children.tsx
    

    在children.tsx中添加如下代码:

    import React from 'react';
    import {Route} from "react-router-dom";
    import MainLayout from '../layout/MainLayout';
    import Home from '../pages/Home/index';
    import Order from '../pages/Order/index';
    import My from '../pages/My/index';
    
    
    export const ChildRouter = (props: any) => (
        <MainLayout {...props}>
            <Route exact path="/" component={Home}/>
            <Route exact path="/index" component={Home}/>
            <Route path="/index/home" component={Home}/>
            <Route path="/index/order" component={Order}/>
            <Route path="/index/my" component={My}/>
        </MainLayout>
    );
    

    在index.tsx中添加如下代码:

    import React from 'react';
    import {HashRouter, Route, Switch} from "react-router-dom";
    
    import {ChildRouter} from './children';
    
    const BasicRouter = () => (
        <HashRouter>
            <Switch>
                <Route exact path="/" component={ChildRouter}/>
                <Route path="/index" component={ChildRouter} />
            </Switch>
        </HashRouter>
    );
    
    export default BasicRouter;
    

    在App.tsx中,作如下改动:

    import React from 'react';
    import 'antd/dist/antd.css';
    import './App.scss';
    import BasicRouter from './route';
    
    function App() {
        return (
            <BasicRouter/>
        );
    }
    
    export default App;
    

    至此,一个嵌套路由就配置好了,在浏览器中输入localhost:3000/#/看看会出现什么。

    编写Tabs组件

    在src下新建components文件夹及Tabs文件夹,Tabs文件夹下再新建index.tsx、index.scss:

    |-src
        |-components
            |-index.tsx
            |-index.scss
    

    在index.tsx中编写如下代码:

    import React from 'react';
    import './index.scss';
    
    interface IProps {
        onTabChange: Function;
        activeIndex: number;
        tabList: any[];
    }
    
    const Tabs: React.FC<IProps> = (props) => {
    
        return (
            <div className='tabs-wrap'>
                {
                    props.tabList.map(item => (
                        <div
                            key={item.key}
                            className={props.activeIndex === item.key ? 'tabs-item active' : 'tabs-item'}
                            onClick={() => {
                                props.onTabChange(item.key);
                            }}
                        >
                            <i className={`tabs-icon ${item.icon}`}></i>
                            <br/>
                            {item.text}
                        </div>
                    ))
                }
            </div>
        )
    };
    
    export default Tabs;
    

    编写样式:

    .tabs-wrap {
      position: fixed;
      display: flex;
      align-items: center;
      justify-content: center;
      bottom: 0;
      width: 100%;
      height: 50px;
      border-top: 1px solid #e0e0e0;
    
      .tabs-item {
        flex: 1;
        text-align: center;
        font-size: 12px;
        color: #8a8a8a;
    
        &.active {
          color: #1296db;
    
          .tabs-icon.home {
            background: url("../../assets/home1.png") center no-repeat;
            background-size: contain;
          }
    
          .tabs-icon.order {
            background: url("../../assets/order1.png") center no-repeat;
            background-size: contain;
          }
    
          .tabs-icon.my {
            background: url("../../assets/my1.png") center no-repeat;
            background-size: contain;
          }
        }
    
        .tabs-icon {
          display: inline-block;
          width: 25px;
          height: 25px;
          margin-bottom: 4px;
        }
    
        .tabs-icon.home {
          background: url("../../assets/home.png") center no-repeat;
          background-size: contain;
        }
    
        .tabs-icon.order {
          background: url("../../assets/order.png") center no-repeat;
          background-size: contain;
        }
    
        .tabs-icon.my {
          background: url("../../assets/my.png") center no-repeat;
          background-size: contain;
        }
      }
    }
    

    图标请到iconfont或GitHub仓库自行下载。
    然后修改MainLayout.tsx:

    import React from 'react';
    import './MainLayout.scss';
    import Tabs from '../components/Tabs/index';
    
    interface IProps {
        history: any;
        location: any;
    }
    
    interface IState {
        collapsed: Boolean;
        activeIndex: number;
    }
    
    export default class MainLayout extends React.Component<IProps, IState> {
        state: IState = {
            collapsed: false,
            activeIndex: 0,
        };
    
        tabList: any[] = [
            {
                key: 0,
                text: '点餐',
                icon: 'home',
            },
            {
                key: 1,
                text: '订单',
                icon: 'order',
            },
            {
                key: 2,
                text: '我的',
                icon: 'my',
            },
        ];
    
        componentDidMount(): void {
            const {location} = this.props;
            let activeIndex = 0;
            switch (location.pathname) {
                case '/':
                    activeIndex = 0;
                    break;
                case '/index/order':
                    activeIndex = 1;
                    break;
                case '/index/my':
                    activeIndex = 2;
                    break;
                default:
                    break;
            }
            this.setState({activeIndex});
        }
    
        toggle = (): void => {
            this.setState({
                collapsed: !this.state.collapsed,
            });
        };
    
        handleChange = (index: number): void => {
            const {history} = this.props;
            let url = '/';
            switch (index) {
                case 0:
                    url = '/';
                    break;
                case 1:
                    url = '/index/order';
                    break;
                case 2:
                    url = '/index/my';
                    break;
                default:
                    break;
            }
            this.setState({
                activeIndex: index,
            });
            history.replace(url);
        };
    
        render() {
            const {activeIndex} = this.state;
            return (
                <div className='main-layout'>
                    <div className='page-wrapper'>
                        {this.props.children}
                    </div>
                    <Tabs onTabChange={this.handleChange} activeIndex={activeIndex} tabList={this.tabList}/>
                </div>
            );
        }
    }
    

    打开浏览器查看效果


    图1.png

    至此,一个Tabs组件的开发完成。

    相关文章

      网友评论

        本文标题:仿饿了么H5项目-React+antd-mobile实战(二)-

        本文链接:https://www.haomeiwen.com/subject/xiftbctx.html