umi框架的使用

作者: koala949 | 来源:发表于2019-12-31 19:47 被阅读0次

介绍umi

umi官方文档

初探

对比以往使用的 create-react-app 搭建react项目,根据需要我们还得集合webpack打包,或者引入redux状态管理器等,而umi ---
通过 create-umi提供脚手架能力,
然后我们可以选择需要生成的项目类型:

  • app,通用项目脚手架,支持选择是否启用 TypeScript,以及 umi-plugin-react 包含的功能
  • ant-design-pro,仅包含 ant-design-pro 布局的脚手架,具体页面可通过 umi block 添加
  • block,区块脚手架
  • plugin,插件脚手架
  • library,依赖(组件)库脚手架,基于 umi-plugin-library
    之后选择是否需要支持typescript
    然后选择需要的功能:
  • antd: UI框架,启用后实现antd, antd-mobile 和 antd-pro 的按需编译,无需要手动配置。
  • dva: 基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架
  • code splitting: 是否代码分包
  • dll: 通过 webpack 的 dll 插件预打包一份 dll 文件来达到二次启动提速的目的
    按上下箭头移动,并按 空格 键选中。

确定后,会根据选择自动创建好目录和文件

安装依赖,yarn start启动项目。

路由

umi 以路由为基础的,支持类 next.js 的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载

(1) 无需手动配置路由
根据pages目录自动生成路由配置,会根据 src / pages 下 文件名自动生成路由
(也可以配置.umirc.js中的 routes 属性,此配置项存在时则不会对 src/pages 目录做约定式的解析)
(2) 其他基础知识:

  • 动态路由:带 $ 前缀的目录或文件。
    目录结构:

      + pages/
      + $post/
        - index.js
        - comments.js
      + users/
        $id.js
      - index.js
    

    会生成的路由配置:

      [
        { path: '/', component: './pages/index.js' },
        { path: '/users/:id', component: './pages/users/$id.js' },
        { path: '/:post/', component: './pages/$post/index.js' },
        { path: '/:post/comments', component: './pages/$post/comments.js' },
      ]
    
  • 可选的动态路由:
    约定动态路由如果带 $ 后缀,则为可选动态路由。

(3)常用的路由操作

  import Link from 'umi/link';
  import router from 'umi/router';
  • 普通使用
    <Link to="/list">跳转</Link>

  • 带参数
    <Link to="/list?a=b">跳转</Link>

  • 包含子组件
    <Link to="/list?a=b"><button>跳转</button></Link>

  • 点击跳转
    <button onClick={() => router.push('/list')}>跳转</button>

  • router.push

         // 普通跳转,不带参数
          router.push('/list');
          // 带参数
          router.push('/list?a=b');
          router.push({ pathname: '/list', query: { a: 'b' } });
    
  • router.replace

  • router.go(n)
    往前或者往后跳指定页数。

  • router.goBack()
    后退一页

  • umi/redirect
    重定向

      import Redirect from 'umi/redirect';
      <Redirect to="/login" />;
    
  • withRouter
    当组件需要路由参数时,使用withRouter可以给当前组件传入路由参数,将react-router的history、location、match三个对象传入props对象上,此时就可以使用this.props

布局

(1)全局layout
约定 src/layouts/index.js 为全局路由,返回一个 React 组件,通过 props.children 渲染子组件。
比如:

    export default function(props) {
      return (
        <>
          <Header />
          { props.children }
          <Footer />
        </>
      );
    }

(2)不同的全局layout
可以在 layouts/index.js 对 location.path 做区分,渲染不同的 layout 。
比如想要针对 /login 输出简单布局:

  export default function(props) {
    if (props.location.pathname === '/login') {
      return <SimpleLayout>{ props.children }</SimpleLayout>
    }

    return (
      <>
        <Header />
        { props.children }
        <Footer />
      </>
    );
  }

(3)尝试
要求: 登录页和首页显示不同的布局


根据路由渲染不同的布局

同样对 location.path 做区分,但是如果是动态路由或者嵌套路由这样的匹配是有漏洞的。

优化后:
配置路由对应的布局,默认使用NavigatorLayout

    const routeLayoutMap = [{
      matches: ['/users', '/login', '/contact-sale'],
      component: BlankLayout,
    }, {
      matches:[],
      component: NavigatorLayout,
    }];

    const res = routeLayoutMap.find(({ matches }) => {
        return checkRouteMatch(matches, location.pathname)
      });
      const layout = res ? res.component : NavigatorLayout
      return React.createElement(layout, props);
    }

根据正则判断

    function checkRouteMatch (routes, pathname) {
      const _routes = routes.map(one => {
        if (isString(one) || isRegExp(one)) one = { match: one }
        if (!isObject(one)) return {}
        const { match, exclude } = one
        return {
          match,
          exclude: (isArray(exclude) || !exclude) ? exclude : [exclude]
        };
      })
      return _routes.some(({ match, exclude }) => {
        function check (rule, value) {
          if (isString(rule)) return value.includes(rule);
          if (isRegExp(rule)) return rule.test(value);
          return false;
        }
        const res = check(match, pathname)
        if (!res) return false;
        if (!isArray(exclude) || !exclude.length) return res;
        return !exclude.some(one => check(one, pathname))
      })
    }

mock

用之前先把mock使用示例看看==>mock.js文档
(1)在umi中使用mock:

  • 新建mock数据:
    在 mock 文件下新建文件 users.js 为保存mock数据的一个文件。

    import mockjs from 'mockjs';
    
    let dataSource = mockjs.mock({
      'list|15-30': [{
          'id': () => mockjs.Random.guid(),
          'name': /[a-zA-Z0-9]{4,8}/,
          'email': /[a-zA-Z0-9]{4,8}@test\.com/,
          'website': /[a-zA-Z0-9]{4,8}/
      }]
    }).list;
    
    export default {
      'GET /api/users': (req, res) => {
        const { page = 0, size = 10 } = req.query
        const _page = parseInt(page, 10)
        const _size = parseInt(size, 10)
        const data = dataSource.slice(_page * _size, (_page + 1) * _size);
        res.json({
          content: data,
          number: _page,
          size: _size,
          totalElements: dataSource.length,
        })
      },
    }
    
  • 调用数据
    输入路径可直接获取数据,:/api/users

  • 排除 mock 目录下不作 mock 处理的文件。
    在config/config.start-dev.js文件中使用exclude
    mock: {
    exclude: ['mock/login.js']
    },

其他探索...(后期更新)

相关文章

网友评论

    本文标题:umi框架的使用

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