umi框架的使用

介紹umi

umi官方文檔

初探

對比以往使用的 create-react-app 搭建react項目,根據(jù)需要我們還得集合webpack打包,或者引入redux狀態(tài)管理器等,而umi ---
通過 create-umi提供腳手架能力,
然后我們可以選擇需要生成的項目類型:

  • app,通用項目腳手架,支持選擇是否啟用 TypeScript,以及 umi-plugin-react 包含的功能
  • ant-design-pro,僅包含 ant-design-pro 布局的腳手架,具體頁面可通過 umi block 添加
  • block,區(qū)塊腳手架
  • plugin,插件腳手架
  • library,依賴(組件)庫腳手架,基于 umi-plugin-library
    之后選擇是否需要支持typescript
    然后選擇需要的功能:
  • antd: UI框架,啟用后實現(xiàn)antd, antd-mobile 和 antd-pro 的按需編譯,無需要手動配置。
  • dva: 基于 redux 和 redux-saga 的數(shù)據(jù)流方案,然后為了簡化開發(fā)體驗,dva 還額外內(nèi)置了 react-router 和 fetch,所以也可以理解為一個輕量級的應用框架
  • code splitting: 是否代碼分包
  • dll: 通過 webpack 的 dll 插件預打包一份 dll 文件來達到二次啟動提速的目的
    按上下箭頭移動,并按 空格 鍵選中。

確定后,會根據(jù)選擇自動創(chuàng)建好目錄和文件

安裝依賴,yarn start啟動項目。

路由

umi 以路由為基礎的,支持類 next.js 的約定式路由,以及各種進階的路由功能,并以此進行功能擴展,比如支持路由級的按需加載。

(1) 無需手動配置路由
根據(jù)pages目錄自動生成路由配置,會根據(jù) src / pages 下 文件名自動生成路由
(也可以配置.umirc.js中的 routes 屬性,此配置項存在時則不會對 src/pages 目錄做約定式的解析)
(2) 其他基礎知識:

  • 動態(tài)路由:帶 $ 前綴的目錄或文件。
    目錄結(jié)構:

      + 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' },
      ]
    
  • 可選的動態(tài)路由:
    約定動態(tài)路由如果帶 $ 后綴,則為可選動態(tài)路由。

(3)常用的路由操作

  import Link from 'umi/link';
  import router from 'umi/router';
  • 普通使用
    <Link to="/list">跳轉(zhuǎn)</Link>

  • 帶參數(shù)
    <Link to="/list?a=b">跳轉(zhuǎn)</Link>

  • 包含子組件
    <Link to="/list?a=b"><button>跳轉(zhuǎn)</button></Link>

  • 點擊跳轉(zhuǎn)
    <button onClick={() => router.push('/list')}>跳轉(zhuǎn)</button>

  • router.push

         // 普通跳轉(zhuǎn),不帶參數(shù)
          router.push('/list');
          // 帶參數(shù)
          router.push('/list?a=b');
          router.push({ pathname: '/list', query: { a: 'b' } });
    
  • router.replace

  • router.go(n)
    往前或者往后跳指定頁數(shù)。

  • router.goBack()
    后退一頁

  • umi/redirect
    重定向

      import Redirect from 'umi/redirect';
      <Redirect to="/login" />;
    
  • withRouter
    當組件需要路由參數(shù)時,使用withRouter可以給當前組件傳入路由參數(shù),將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 做區(qū)分,渲染不同的 layout 。
比如想要針對 /login 輸出簡單布局:

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

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

(3)嘗試
要求: 登錄頁和首頁顯示不同的布局


根據(jù)路由渲染不同的布局

同樣對 location.path 做區(qū)分,但是如果是動態(tài)路由或者嵌套路由這樣的匹配是有漏洞的。

優(yōu)化后:
配置路由對應的布局,默認使用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);
    }

根據(jù)正則判斷

    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數(shù)據(jù):
    在 mock 文件下新建文件 users.js 為保存mock數(shù)據(jù)的一個文件。

    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,
        })
      },
    }
    
  • 調(diào)用數(shù)據(jù)
    輸入路徑可直接獲取數(shù)據(jù),:/api/users

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

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

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容