zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    element ui 表单清空
    element ui 覆盖样式 方法
    element ui 修改表单值 提交无效
    element ui 抽屉里的表单输入框无法修改值
    element ui 抽屉首次显示 闪烁
    css 左侧高度 跟随右侧内容高度 自适应
    PICNUF框架
    elementui 抽屉组件标题 出现黑色边框
    vue 子组件跨多层调用父组件中方法
    vue 编辑table 数据 未点击提交,table里的数据就发生了改变(深拷贝处理)
  • 原文地址:https://www.cnblogs.com/rachelch/p/13878202.html
Copyright © 2011-2022 走看看