【Umi 一】 Umi 搭建配置


螞蟻金服開源的企業級React框架,並不是UI框架

1.特性

  1. 開箱即用,內置 reactreact-router ...
  2. 類似 next.js 且功能完備的路由約定,同時也支持手動配置路由的方式;
  3. 完善的插件體系,高性能,通過插件支持PWA、以路由為單元的code splitting等等;
  4. 支持靜態頁面導出,適配各種環境,如中台業務、無線業務、egg、支付寶錢包
  5. 開發啟動快,支持一鍵開啟dll
  6. 一鍵兼容IE9、基於 umi-plugin-polyfills
  7. 支持TypeScript
  8. dva 數據流的深入融合,支持duck directory、model的自動加載、code splitting等等
2. dva 是React應用框架,封裝了  ReduxRedux-sagaReact-router 三個React工具庫,目前 React 最流行的數據流解決放案;


1. State:一個對象,保存整個應用狀態;
2. View:React組件構成的視圖層;
3. Action:一個對象,描述事件
4. connect():綁定```State``````View``` 5. dispatch():發送```Action``````State```

3.dvaumi 的約定

        1.src 源碼:pages(頁面)、components(組件)、layout(布局)、model(數據模型)

        2.config 配置

        3.mock 數據模擬

        4.test 測試

4.全局安裝腳手架: npm i umi -g
 

快速上手

1、創建一個項目目錄:mkdir myumi
2、 cd myumi 
3、 npm init:生成 package.json
"scripts": {
    "start": "umi dev",
    "build": "umi build"
}
4、創建 src 目錄,生成 pages 目錄,默認使用約定式路由
cd src
umi g page index  // index.js和index.css
umi g page about  // bout.js和about.css

5、運行項目:npm start,自動編譯生成頁面配置 /src/pages/.umi 目錄,且項目是熱部署;

http://localhost:8000/  --> index.js
http://localhost:8000/about  --> about.js

6、引入公共 css (根據個人需求,可要可不要)

在 src 目錄下新建 global.css/.less 

7、創建全局布局 layouts,如公共頭部、尾部  (根據個人需求,可要可不要)

src/layouts 目錄中的 index.js 將成為項目的定級布局頁面,使用 {props.children} 顯示 src/pages 目錄中的組件。

在 src 目錄下,創建文件夾 layouts
在 layouts 目錄下,創建 index.js、index.less
import styles from './index.css';
import {Layout} from 'antd';
const {Header, Content, Footer} = Layout;

export default (props) => {
    return (
        <Layout>
            <Header>
                <div style={{color: 'white'}}>王者資料庫</div>
            </Header>
            <Content style={{padding: '0 50px'}}>
                {props.children}
            </Content>
            <Footer style={{textAlign: 'center'}}>footer</Footer>
        </Layout>
    )
}

約定式路由嵌套 (Link、history)

1、當出現 _layout.js 頁面時默認為父組件頁面,通過 {props.children} 顯示子組件內容;

2、嵌套路由:/users,創建 pages/users 目錄

umi g page users/_layout    // pages/users/_layout.js、_layout.css

        1.pages/users/_layout.js

import React from 'react';
import styles from './_layout.css';

export default (props) => {
  return (
    <div className={styles.normal}>
      <h1 className={styles.title}>Page users/_layout</h1>
      <div>{props.children}</div>
    </div>
  );
}

        2.為 _layout.js 創建子組件,users 的首頁 index.js

 umi g page users/index    // pages/users/index.js、index.css

         3.訪問嵌套路由:http://localhost:8000/users

 3、約定 [] 包裹的文件或文件夾為動態路由、users/[name].js 對應路由為 /users/:name

  1. users 目錄中,再創建 [name].js、[name].css
  2. 訪問 [name].jshttp://localhost:8000/users/xxx

4、跳轉路由 (Link,history)

         1.users/index.js

import React from 'react';
import styles from './index.css';
import {Link} from 'umi';

export default () => {
    const userList = [
        {id: 1, name: 'Tim'}, {id: 2, name: 'Jarry'}
    ]
  return (
    <div>
      <ul>
      {
          userList.map(item => (
              <li key={item.id}>
                  <Link to={`/users/${item.name}`}>{item.name}</Link>
              </li>
          ))
      }
      </ul>
    </div>
  );
}

          2.users/[name].js

import React from 'react';
import styles from './[name].css';
import {history} from 'umi';

export default (props) => {
  return (
    <div>
      <h1 className={styles.title}>Page users/[name]</h1>
      <h2>{props.match.params.name}</h2>
        <button onClick={()=>props.history.goBack()}>返回</button>
    </div>
  );
}

 

配置式路由

1、配置式路由一旦創建,約定式路由自動失效,umi不會再自動創建路由;

2、在項目根目錄下創建 config 目錄,並創建 config.js文件;

// 沒有設置全局 layouts 布局
export default {
    // 路由配置:路徑相對於 src/pages
    routes: [
        {path: '/', component: './index'},
        {path: '/about', component: './about'},
        {
            path: '/users',
            component: './users/_layout',
            routes: [
                {path: '/users', component: './users/index'},
                {path: '/users/:name', component: './users/[name]'},
            ]
        },
        {component: './notfound'} // 404頁面,上面的所有路由都沒有匹配時,則匹配404頁面
    ],
}
// 設置了全局 layouts 布局
export default {
    // 路由配置:路徑相對於 src/pages
    routes: [
        {
            path: '/', 
            component: '../layouts/index',
            routes: [
                {path: '/', component: './index'},
                {path: '/about', component: './about'},
                {
                    path: '/users',
                    component: './users/_layout',
                    routes: [
                        {path: '/users', component: './users/index'},
                        {path: '/users/:name', component: './users/[name]'},
                    ]
                },
            ]
        },
    ],
}

3、相應地,創建404組件:umi g page notfound

4、引入ant design UI庫

npm i antd -S
npm i @umijs/preset-react -D (umi3升級)

         1.config/config.js

    export default {
        //路由配置
        routes: [...],
        antd: {},
    }

          2.使用時需要導入組件,因為是按需加載

import {Button} from 'antd';

<Button type="success">antd Btn</Button>

引入dva

1、dva 主要是軟件分層的概念

          1.Page 負責與用戶直接交互:渲染頁面、接收用戶的操作輸入,側重於展示型和交互邏輯;

          2.Model 負責處理業務邏輯,可以理解成一個維護頁面數據狀態的對象,為 Page 做數據、狀態的讀寫等操作;

    export default {
        namespace: 'goods',  // model的命名空間,區分多個model
        state: [],  //初始狀態
        effects: {  //異步操作
        },
        reducers: {}
    }

            3.Service 主要負責與HTTP做接口對接,跟后端做數據交互,讀寫數據;

2、dva 已經融合進了 umi,在 config/config.js 中打開 dva 的開關

antd: {},
dva: {}

基本用法

umi g page goods
npm i axios -S

1、路由配置:config/config.js (如果使用約定式路由,則無須配置)

routes: [
    { path: "/goods", component: "./goods" },
]

2、在項目根目錄下創建 mock/goods.js,模擬接收請求,響應數據

let data = [
  {title: '單頁面'},
  {title: '管理項目3'}
]
export default {
  'get /api/goods': function(req, res){
    setTimeout(() => {
      res.json({result: data})
    }, 1000)
  }
}

3、Modelsrc/models/goods,js

import axios from 'axios';

//調接口的邏輯應該放在 Service 層
function getGoods(){
  return axios.get('/api/goods')
}

export default{
    namespace: 'goods',  // 命名空間,如果省略,則以文件名作為命名空間
    state: [],
    effects: {
        *getList(action, {call , put}){ // 異步操作
            const res = yield call(getGoods);  // 發起請求
            yield put({type: 'initGoods', payload: res.data.result})  // 派發異步action: initGoods 
        }
    },
    reducers: {
        initGoods(state, action){
            return action.payload
        },
        addGood(state, action){
            return [...state, {title: action.payload.title}]
        },
        delGood(state, action){
            return [...state.slice(0,action.payload.index),...state.slice(action.payload.index+1)];
        }
    }
}

4、pages/goods.js

import React, { Component} from 'react';
import styles from './goods.css';
import {connect} from 'dva';

// @connect 必須放在 export default class 前面
@connect(
  state => ({
    goodList: state.goods, // 從指定命名空間內獲取state
    loading: state.loading // 通過loading命名空間獲取加載的狀態
  }), 
  {
    getList: () => ({
      type: 'goods/getList' // action的type需要以命名空間為前綴,后跟reducer
    }),
    addGood: title => ({
      type: 'goods/addGood',
      payload: {title}
    }),
    delGood: index => (
        {
            type: 'goods/delGood',
            payload: {index}
        }
    )
  }
)

export default class extends Component{
  componentDidMount(){
    this.props.getList(); // 觸發事件,發起請求,獲取數據
  }
  render(){
    if(this.props.loading.models.goods){
        // 命名空間goods 的請求在加載中
      return <div>loading</div>
    }
    return (
      <div>
        <ul>
          {
            this.props.goodList.map((good, index) => {
              return <li key={index}>{good.title}<button style={{marginLeft: '100px', marginBottom: '10px'}} onClick={() => this.props.delGood(index)}>刪除</button></li>
            })
          }
        </ul>
        <button onClick={() => this.props.addGood('商品3')}>添加</button>
      </div>
    )
  }
}

 

【常見報錯問題】

1、reactjs頁面無法引入umi/link

【Umi 二】reactjs頁面無法引入umi/link

 2、Path must be a string. 

【Umi 三】 Umi項目啟動報錯:Path must be a string.

3、Cannot find module 'umi'

【Umi 四】 Cannot find module 'umi'

 

參考文章:umi

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM