zoukankan      html  css  js  c++  java
  • 《umi+ts+antd Pro 珠峰课程【1】》

    https://www.bilibili.com/video/BV1JJ411q7iw

    umi+ts+antd Pro 珠峰课程

     

     

     

    npm install -g cnpm --registry=https://registry.npm.taobao.org

    cnpm install -g yarn

    yarn create umi 

     

    git init 

    npm i

     扩展 window,加了一些属性

    umi+dva 项目快速上手指南

    在 react 项目中,使用 react+umi+dva+antd 这一阿里系列技术栈的人越来越多,本文就来分享一下 umi 项目的上手教程。在 react 项目中,使用 react+umi+dva+antd 这一阿里系列技术栈的人越来越多,本文就来分享一下 umi 项目的上手教程。

    构建项目

    node 环境

    node 版本 >= 8.0.0

    全局安装 umi

    npm install -g umi 

    建议使用 yarn 安装

    // 全局安装yarn
    npm install -g yarn
    
    // 使用yarn安装umi
    yarn global add umi

    构建 umi 项目

    mkdir myapp && cd myapp
    yarn create umi

    详细构建请参考 umi 官方项目构建

    目录结构

    ├── config/
        ├── config.js                  // umi 配置,同 .umirc.js,二选一
    ├── dist/                          // 默认的 build 输出目录
    ├── mock/                          // mock 文件所在目录,基于 express
    ├── public/                        // 全局相对路径文件
    └── src/                           // 源码目录,可选
        ├── assets/                    // 静态文件
        ├── components/                // 全局共用组件
        ├── layouts/index.js           // 全局入口文件
        ├── models/                    // 全局models文件,存放全局共用数据store
        ├── pages/                     // 页面目录,业务组件
            ├── .umi/                  // dev 临时目录,需添加到 .gitignore
            ├── .umi-production/       // build 临时目录,会自动删除
            ├── index/                 // 首页模块
            ├── manager/               // 管理端模块
                ├── components/        // 管理端-局部公共组件
                ├── models/            // 管理端-局部models,存放manager的store
                ├── services/          // 管理端-局部services,存放manager的接口
                ├── index.js           // 业务组件index
                ├── page.js            // 业务组件page
                ├── _layout.js         // 局部入口文件
            ├── 404.js                 // 404 页面
        ├── services/                  // 全局services文件,存放全局公共接口
        ├── utils/                     // 全局工具类
        ├── global.css                 // 约定的全局样式文件,自动引入,也可以用 global.less
        ├── global.js                  // 约定的全局Js文件,自动引入,可以在这里加入 polyfill
        ├── app.js                     // 运行时配置文件
    ├── .umirc.js                      // umi 配置,同 config/config.js,二选一
    ├── .env                           // 环境变量
    └── package.json

    配置文件

    umi 允许在 .umirc.js 或 config/config.js (二选一,.umirc.js 优先)中进行配置,支持 ES6 语法。本文使用 config/config.js

    export default {
      base: '/web/',  //部署到非根目录时才需配置
      targets: { //配置浏览器最低版本,比如兼容ie11
       ie: 11
      },
      hash: true,  //开启打包文件的hash值后缀
      treeShaking: true, //去除那些引用的但却没有使用的代码
      plugins: [
        [
          'umi-plugin-react',
          {
            antd: true, //启用后自动配置 babel-plugin-import,实现antd按需加载
            dynamicImport: { //实现路由级的动态加载
              webpackChunkName: true //实现有意义的异步文件名
            },
            dva: {
              dynamicImport: true, //是否启用按需加载
              hmr: true //是否启用 dva 的 热更新
            },
            //通过 webpack 的 dll 插件预打包一份 dll 文件来达到二次启动提速的目的
            dll: {
              exclude: [],
              include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch', 'antd/es']
            },
            //约定式路由时才需引用,用于忽略指定文件夹中自动生成的路由
            routes: {
              exclude: [
                /components//,
                /model.(j|t)sx?$/,
                /components.(j|t)sx?$/,
                /service.(j|t)sx?$/,
                /models//,
                /services//
              ],
            },
          }
        ]
      ],
      //配置式路由时,路由文件由此引用(往下会讲到)
      routes: routes,
      //代理请求
      proxy: {
        "/api": {
          "target": "http://jsonplaceholder.typicode.com/",
          "changeOrigin": true,
          "pathRewrite": { "^/api" : "" }
        }
      },
      alias: {'@': resolve(__dirname, '../src'),} //别名,umirc.js为'src'
    };

    pages

    + pages
      + manager
        + components/
        + models/
        + services/
        - index.js
        - _layout.js

    业务目录中,标配局部公用组件 components,局部共用数据 models,局部共用接口 services,_layout.js 入口文件需要则引入。

    路由

    1. 约定式路由

    1.1 umi 约定,在 pages 目录下的. js/.jsx 会自动生成路由,除开在配置文件 plugins/routes 中被 exclude 的目录或文件,文件的路径即路由。 1.2 src/layout / 为全局 layout,默认全局入口文件,配置式路由下无效。pages / 下任何文件下的_layout.js 即当前文件夹路由下的入口文件,必须先经过_layout.js 才能进入当前文件夹路由

    2. 配置式路由

    在配置文件 .umirc.(ts|js) 或者 config/config.(ts|js) 中引入:

    export default {
      routes: [
        {
          path: '/',
          component: '../layouts/index',
          routes: [
            { path: '/user', redirect: '/user/login' },//redirect,避免只渲染_layout.js
            { path: '/user/login', component: './user/login' },
            {
              path: '/manager', component: '../pages/management/_layout.js',
              routes: [
                { path: '/manager/system', component: '../pages/management/manager/system', Routes: ['./routes/PrivateRoute.js'] }
            }
          ],
        },
      ],
    };

    3. 权限路由

    路由通过 Routes 属性来实现权限路由, 如上文:/manager/system 路由。创建一个./routes/PrivateRoute.js 权限文件,props 里会传入 / manager/system 的路由信息。

    export default (props) => {
      return (
        <div>
          <div>PrivateRoute (routes/PrivateRoute.js)</div>
          { props.children }
        </div>
      );
    }

    4. 跳转路由

    link 方式

    import Link from 'umi/link';
      <Link to="/list">Go to list page</Link>

    router 方式

    import router from 'umi/router';
      router.push({
        pathname: '/list',
        query: {
          a: 'b',
        },
      });

    models 层

    models/index.js,不能空文件。由于 umi/dva 是基于 redux,redux-saga 的数据流方案,dva 的 connect 即 redux 的 connect,dva 的 model 即 redux-saga 简化版,更易用。

    import * as services from '../services';
    {
      namespace: 'system',   //models命名空间,需全局唯一
      state: {               //models存储的数据store
        dataList: []
      },                     
      reducers: {
        save(state, { payload }) {          //更新store,用新数据合并state的旧数据
          return { ...state, ...payload };
        }
      },
      effects: {
        * testFunc({ payload: params }, { call, put, select }) {   //dispatch请求的方法
          const { dataList } = yield select(state => state.system); //获取models中的state
          const { data } = yield call(services.testFunc, params);  //call,请求services里面的接口以及传参,可继续往后面加参数,跟JavaScript的call一样
          if (data && data.code == 0) {
            const data_ = data.data.content;
            yield put({ //put,必须发出action save,此action被reducer监听,从而达到更新state数据的目的
              type: 'save',                                        
              payload: {
                dataList: data_ || []
              }
            });
            return data_;   //返回response,可选
          }                                                        
        },
      },
      subscriptions: {      //订阅,在app.start()即启动项目时被执行
        setup({ dispatch, history }) {
          return history.listen(({ pathname, query }) => {
            // 进入 '/manager/system' 路由,会发起一个名叫 'save' 的 effect
            if (pathname === '/manager/system') {
                        //do sth... dispatch({ type: 'save', payload: query });
                    }
          })
        }
      }
    }

    注:call 会阻塞,在 call 方法调用结束之前,call 方法之后的语句是无法执行的,使得以同步的方式执行异步,如需无阻塞,则要引入 fork,用 yield fork 代替 yield call。

    services 层

    请求后台接口的方法,返回一个 promise 对象。

    import request from '@utils/request';
    
    export function rightSave(values) {
      return request(`/authirty/right/save`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(values)
      });
    }

    components 层

    dispatch

    与 effect 中的 put 方法相似,必须触发 action。 在 model 的 subscription 参数中使用。 在组件中,由 connect 过的组件中,组件的 props 中才可以获取到 dispatch。

    import { connect } from 'dva'; 
    export default connect()(System);
    • 接口请求 方式一 (推荐): 使用 dispatch 调用 models 里面 effects/reducer 声明的方法,

    this.props.dispatch({
      type: 'system/testFunc',   //type,命名空间/effects方法名
      payload: params,           //payload,参数
    }).then(res => {})
    
    //直接赋值更新state
    this.props.dispatch({
      type: 'system/save',  //type,命名空间/reducer方法名
      payload: {
        rightDetail: {a:1}
      },                    //payload,参数
    }).then(res => {})
    
    //请求全局model
    this.props.dispatch({
      type: 'global/getOrganizationList',  //全局namespace/全局effects方法名
      payload: params,                     //payload,参数
    }).then(res => {})

    方式二:dispatch 带 callback 回调函数作为第三个参数

    //组件中
    this.props.dispatch({
      type: 'system/testFunc',
      payload: params,
      callback: (res) => {
        if (!!res) {
          //do sth
        }
      }
    });
    
    //model中
    *testFunc({ payload, callback }, { call, put }){
      const { data } = yield call(services.rightSave, payload);
      if (data && data.code == 0) {
        !!callback && && callback(data);
      }
    }

    方式三 (少用):如果组件中不需要用到 model 存 store 时,直接引入 services 请求接口

    //组件中
    //使用new promise请求接口,service返回promise函数,待接口异步请求完才执行.then
    import * as service from '../services'; 
    new Promise((resolve) => {
      const ret = service.rightSave(param);
      resolve(ret);
    }).then((ret) => {
      if (ret && ret.code == 200) {
        //do sth
      }
    });
    
    // 或者
    // 现在的ajax框架返回的就是一个promise的话,可以直接方法名跟上.then()即可
    import { rightSave } from '../services';
    rightSave().then(res => {
      let data = res.data;
      if (data && data.code == 200) {
        //do sth
      }
    });

    connect

    方式一:mapStateToProps,class 继承组件和函数组件都能用这种

    接口请求完后,组件中引入 connect,获取 models 的数据放入当前组件 props 中

    import { connect } from 'dva'; 
    function mapStateToProps(state) { //state是项目所有的models
      const { selectList } = state.system; //获取namespace命名空间为system的models数据state
      const { organizationList } = state.global; //全局获取namespace命名空间为global的models数据state
      return {
        selectList,
        organizationList
      };
    }
    export default connect(mapStateToProps)(System);   //connect组件
    //或者直接解构
    export default connect(({ system, global: { organizationList } }) => ({ ...system, organizationList }))(System);

    方式二:es6 注解方式引入,只能用于 class 继承组件

    @connect(({ system, global: {organizationList} }) => ({ 
      ...system,
      organizationList
    }))
    class System extends React.Component{render(){return {<></>}}}

    withRouter

    withRouter 的作用:未经路由跳转的组件,如子组件想拿到路由的相关信息 location、history、match 等时可用,经路由跳转的页面则默认已有路由信息。 FAQ: 1. url 变化了,但页面组件不刷新,是什么原因? layouts/index.js 里如果用了 connect 传数据,需要用 umi/withRouter 高阶一下

    import withRouter from 'umi/withRouter';
    export default withRouter(connect(mapStateToProps)(LayoutComponent));
    1. 全局 layout 使用 connect 后路由切换后没有刷新? 需用 withRouter 包一下导出的 react 组件,注意顺序。
    import withRouter from 'umi/withRouter';
    export default withRouter(connect()(Layout));

    mock

    export default {
      // 支持值为 Object 和 Array
      'GET /api/users': { users: [1, 2] },
      // 支持自定义函数,API 参考 express@4
      'POST /api/users/create': (req, res) => { res.end('OK'); },
    }

    如请求接口 / api/list,数据返回 {users: [1, 2] }

    数据流程

    最后给大家总结一下 dva 的数据流向: * View 层 dispatch 操作 action –> 触发 models 层 effect 中相应方法 –> 触发 call 发起 services 层请求,获取接口数据 –> 触发 put 发起 reducer 处理相应的 action 更新数据 –> 更新 model 层中 state –> 触发 view 层的 render 方法进行重新渲染 –> 页面更新

    附上数据流向图

    参考文档

    umi 文档:https://umijs.org/zh/guide/ dva 文档:https://dvajs.com/guide/

    ps: 如有纰漏,请留言更正!

    构建项目

    node 环境

    node 版本 >= 8.0.0

    全局安装 umi

    npm install -g umi 

    建议使用 yarn 安装

    // 全局安装yarn
    npm install -g yarn
    
    // 使用yarn安装umi
    yarn global add umi

    构建 umi 项目

    mkdir myapp && cd myapp
    yarn create umi

    详细构建请参考 umi 官方项目构建

    目录结构

    ├── config/
        ├── config.js                  // umi 配置,同 .umirc.js,二选一
    ├── dist/                          // 默认的 build 输出目录
    ├── mock/                          // mock 文件所在目录,基于 express
    ├── public/                        // 全局相对路径文件
    └── src/                           // 源码目录,可选
        ├── assets/                    // 静态文件
        ├── components/                // 全局共用组件
        ├── layouts/index.js           // 全局入口文件
        ├── models/                    // 全局models文件,存放全局共用数据store
        ├── pages/                     // 页面目录,业务组件
            ├── .umi/                  // dev 临时目录,需添加到 .gitignore
            ├── .umi-production/       // build 临时目录,会自动删除
            ├── index/                 // 首页模块
            ├── manager/               // 管理端模块
                ├── components/        // 管理端-局部公共组件
                ├── models/            // 管理端-局部models,存放manager的store
                ├── services/          // 管理端-局部services,存放manager的接口
                ├── index.js           // 业务组件index
                ├── page.js            // 业务组件page
                ├── _layout.js         // 局部入口文件
            ├── 404.js                 // 404 页面
        ├── services/                  // 全局services文件,存放全局公共接口
        ├── utils/                     // 全局工具类
        ├── global.css                 // 约定的全局样式文件,自动引入,也可以用 global.less
        ├── global.js                  // 约定的全局Js文件,自动引入,可以在这里加入 polyfill
        ├── app.js                     // 运行时配置文件
    ├── .umirc.js                      // umi 配置,同 config/config.js,二选一
    ├── .env                           // 环境变量
    └── package.json

    配置文件

    umi 允许在 .umirc.js 或 config/config.js (二选一,.umirc.js 优先)中进行配置,支持 ES6 语法。本文使用 config/config.js

    export default {
      base: '/web/',  //部署到非根目录时才需配置
      targets: { //配置浏览器最低版本,比如兼容ie11
       ie: 11
      },
      hash: true,  //开启打包文件的hash值后缀
      treeShaking: true, //去除那些引用的但却没有使用的代码
      plugins: [
        [
          'umi-plugin-react',
          {
            antd: true, //启用后自动配置 babel-plugin-import,实现antd按需加载
            dynamicImport: { //实现路由级的动态加载
              webpackChunkName: true //实现有意义的异步文件名
            },
            dva: {
              dynamicImport: true, //是否启用按需加载
              hmr: true //是否启用 dva 的 热更新
            },
            //通过 webpack 的 dll 插件预打包一份 dll 文件来达到二次启动提速的目的
            dll: {
              exclude: [],
              include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch', 'antd/es']
            },
            //约定式路由时才需引用,用于忽略指定文件夹中自动生成的路由
            routes: {
              exclude: [
                /components//,
                /model.(j|t)sx?$/,
                /components.(j|t)sx?$/,
                /service.(j|t)sx?$/,
                /models//,
                /services//
              ],
            },
          }
        ]
      ],
      //配置式路由时,路由文件由此引用(往下会讲到)
      routes: routes,
      //代理请求
      proxy: {
        "/api": {
          "target": "http://jsonplaceholder.typicode.com/",
          "changeOrigin": true,
          "pathRewrite": { "^/api" : "" }
        }
      },
      alias: {'@': resolve(__dirname, '../src'),} //别名,umirc.js为'src'
    };

    pages

    + pages
      + manager
        + components/
        + models/
        + services/
        - index.js
        - _layout.js

    业务目录中,标配局部公用组件 components,局部共用数据 models,局部共用接口 services,_layout.js 入口文件需要则引入。

    路由

    1. 约定式路由

    1.1 umi 约定,在 pages 目录下的. js/.jsx 会自动生成路由,除开在配置文件 plugins/routes 中被 exclude 的目录或文件,文件的路径即路由。 1.2 src/layout / 为全局 layout,默认全局入口文件,配置式路由下无效。pages / 下任何文件下的_layout.js 即当前文件夹路由下的入口文件,必须先经过_layout.js 才能进入当前文件夹路由

    2. 配置式路由

    在配置文件 .umirc.(ts|js) 或者 config/config.(ts|js) 中引入:

    export default {
      routes: [
        {
          path: '/',
          component: '../layouts/index',
          routes: [
            { path: '/user', redirect: '/user/login' },//redirect,避免只渲染_layout.js
            { path: '/user/login', component: './user/login' },
            {
              path: '/manager', component: '../pages/management/_layout.js',
              routes: [
                { path: '/manager/system', component: '../pages/management/manager/system', Routes: ['./routes/PrivateRoute.js'] }
            }
          ],
        },
      ],
    };

    3. 权限路由

    路由通过 Routes 属性来实现权限路由, 如上文:/manager/system 路由。创建一个./routes/PrivateRoute.js 权限文件,props 里会传入 / manager/system 的路由信息。

    export default (props) => {
      return (
        <div>
          <div>PrivateRoute (routes/PrivateRoute.js)</div>
          { props.children }
        </div>
      );
    }

    4. 跳转路由

    link 方式

    import Link from 'umi/link';
      <Link to="/list">Go to list page</Link>

    router 方式

    import router from 'umi/router';
      router.push({
        pathname: '/list',
        query: {
          a: 'b',
        },
      });

    models 层

    models/index.js,不能空文件。由于 umi/dva 是基于 redux,redux-saga 的数据流方案,dva 的 connect 即 redux 的 connect,dva 的 model 即 redux-saga 简化版,更易用。

    import * as services from '../services';
    {
      namespace: 'system',                             //models命名空间,需全局唯一
      state: {
        dataList: []
      },                                      //models存储的数据store
      reducers: {
        save(state, { payload }) {                    //更新store,用新数据合并state的旧数据
          return { ...state, ...payload };
        }
      },
      effects: {
        * testFunc({ payload: params }, { call, put, select }) {   //dispatch请求的方法
          const { dataList } = yield select(state => state.system); //获取models中的state
          const { data } = yield call(services.testFunc, params);  //call,请求services里面的接口以及传参,可继续往后面加参数,跟JavaScript的call一样
          if (data && data.code == 0) {
            const data_ = data.data.content;
            yield put({ //put,必须发出action save,此action被reducer监听,从而达到更新state数据的目的
              type: 'save',                                        
              payload: {
                dataList: data_ || []
              }
            });
            return data_;                                          //返回response,可选
          }                                                        
        },
      },
      subscriptions: {                                             //订阅,在app.start()即启动项目时被执行
        setup({ dispatch, history }) {
          return history.listen(({ pathname, query }) => {
            // 进入 '/manager/system' 路由,会发起一个名叫 'save' 的 effect
            if (pathname === '/manager/system') {
                        //do sth... dispatch({ type: 'save', payload: query });
                    }
          })
        }
      }
    }

    注:call 会阻塞,在 call 方法调用结束之前,call 方法之后的语句是无法执行的,使得以同步的方式执行异步,如需无阻塞,则要引入 fork,用 yield fork 代替 yield call。

    services 层

    请求后台接口的方法,返回一个 promise 对象。

    import request from '@utils/request';
    
    export function rightSave(values) {
      return request(`/authirty/right/save`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(values)
      });
    }

    components 层

    dispatch

    与 effect 中的 put 方法相似,必须触发 action。 在 model 的 subscription 参数中使用。 在组件中,由 connect 过的组件中,组件的 props 中可以获取到 dispatch。

    import { connect } from 'dva'; 
    export default connect()(System);
    • 接口请求 方式一 (推荐): 使用 dispatch 调用 models 里面 effects/reducer 声明的方法,

    this.props.dispatch({
      type: 'system/testFunc',                                      //type,命名空间/effects方法名
      payload: params,                                              //payload,参数
    }).then(res => {})
    
    //直接赋值更新state
    this.props.dispatch({
      type: 'system/save',                                          //type,命名空间/reducer方法名
      payload: {
        rightDetail: {a:1}
      },                                              //payload,参数
    }).then(res => {})
    
    //请求全局model
    this.props.dispatch({
      type: 'global/getOrganizationList',                           //全局namespace/全局effects方法名
      payload: params,                                              //payload,参数
    }).then(res => {})

    方式二:dispatch 带 callback 回调函数作为第三个参数

    //组件中
    this.props.dispatch({
      type: 'system/testFunc',
      payload: params,
      callback: (res) => {
        if (!!res) {
          //do sth
        }
      }
    });
    
    //model中
    *testFunc({ payload, callback }, { call, put }){
      const { data } = yield call(services.rightSave, payload);
      if (data && data.code == 0) {
        !!callback && && callback(data);
      }
    }

    方式三 (少用):如果组件中不需要用到 model 存 store 时,直接引入 services 请求接口

    //组件中
    //使用new promise请求接口,service返回promise函数,待接口异步请求完才执行.then
    import * as service from '../services'; 
    new Promise((resolve) => {
      const ret = service.rightSave(param);
      resolve(ret);
    }).then((ret) => {
      if (ret && ret.code == 200) {
        //do sth
      }
    });
    
    // 或者
    // 现在的ajax框架返回的就是一个promise的话,可以直接方法名跟上.then()即可
    import { rightSave } from '../services';
    rightSave().then(res => {
      let data = res.data;
      if (data && data.code == 200) {
        //do sth
      }
    });

    connect

    方式一:mapStateToProps,class 继承组件和函数组件都能用这种

    接口请求完后,组件中引入 connect,获取 models 的数据放入当前组件 props 中

    import { connect } from 'dva'; 
    function mapStateToProps(state) { //state是项目所有的models
      const { selectList } = state.system; //获取namespace命名空间为system的models数据state
      const { organizationList } = state.global; //全局获取namespace命名空间为global的models数据state
      return {
        selectList,
        organizationList
      };
    }
    export default connect(mapStateToProps)(System);   //connect组件
    //或者直接解构
    export default connect(({ system, global: { organizationList } }) => ({ ...system, organizationList }))(System);

    方式二:es6 注解方式引入,只能用于 class 继承组件

    @connect(({ system, global: {organizationList} }) => ({ 
      ...system,
      organizationList
    }))
    class System extends React.Component{render(){return {<></>}}}

    withRouter

    withRouter 的作用:未经路由跳转的组件,如子组件想拿到路由的相关信息 location、history、match 等时可用,经路由跳转的页面则默认已有路由信息。

    FAQ:

    1. url 变化了,但页面组件不刷新,是什么原因? layouts/index.js 里如果用了 connect 传数据,需要用 umi/withRouter 高阶一下

    import withRouter from 'umi/withRouter';
    export default withRouter(connect(mapStateToProps)(LayoutComponent));

    2. 全局 layout 使用 connect 后路由切换后没有刷新? 需用 withRouter 包一下导出的 react 组件,注意顺序。

    import withRouter from 'umi/withRouter';
    export default withRouter(connect()(Layout));

    mock

    export default {
      // 支持值为 Object 和 Array
      'GET /api/users': { users: [1, 2] },
      // 支持自定义函数,API 参考 express@4
      'POST /api/users/create': (req, res) => { res.end('OK'); },
    }

    如请求接口 / api/list,数据返回 {users: [1, 2] }

    数据流程

    最后给大家总结一下 dva 的数据流向: * View 层 dispatch 操作 action –> 触发 models 层 effect 中相应方法 –> 触发 call 发起 services 层请求,获取接口数据 –> 触发 put 发起 reducer 处理相应的 action 更新数据 –> 更新 model 层中 state –> 触发 view 层的 render 方法进行重新渲染 –> 页面更新

    附上数据流向图

    参考文档

    umi 文档:https://umijs.org/zh/guide/

    dva 文档:https://dvajs.com/guide/

     

    构建项目node 环境全局安装 umi构建 umi 项目目录结构配置文件pages路由1. 约定式路由2. 配置式路由3. 权限路由4. 跳转路由models 层services 层components 层dispatchconnectwithRoutermock数据流程参考文档构建项目node 环境全局安装 umi构建 umi 项目目录结构配置文件pages路由1. 约定式路由2. 配置式路由3. 权限路由4. 跳转路由models 层services 层components 层dispatchconnectwithRoutermock数据流程参考文档


    https://preview.pro.ant.design/

    admin

    ant.design

    没有注册页面,编写一个注册页面

    先看:什么是一个 block 

     以前是全部自动下载,现在需要自己下载 block 

    umi block list 

    项目启动起来:

    Umi UI 是新的工具 

     两个用户,admin 和 user 

    pw 都是 ant.design

    user 比admin 权限少,看不到管理页

    登录后跳转到之前页面——通过 ?redirect 参数实现

     

      

     

      

     

     

     

     

      

     

     

    effects:副作用,这里用的 saga 的用法

    form:高阶组件用法

    可以收集段的值,也可以进行校验

    force: true —— 强行校验

      payload:携带的数据

    userAndRegister 命名空间,在models 里面定义的

      

    ...: ES6扩展新语法:

    https://blog.csdn.net/qq_30100043/article/details/53391308

     

     

     这个 interface 一会定义后端的接口需要用到

    @ 表示根目录 

     因为拦截了mock,直接校验通过

     

    JSON Web Token 入门教程- 阮一峰的网络日志

    www.ruanyifeng.com › 首页 › 档案
     
    2018年7月23日 - JSON Web Token(缩写JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法。 一、跨域认证的问题. 互联网服务离不开用户认证。

     

     

     不可以,想知道为什么得用 saga —— 基于 saga 都是  generator 模式

    对外umi,对内 bigfish 

    单点登录,非常复杂,不是一般前端能搞得定的

    qiankun:

    权限系统怎么处理的:

    来个 swagger 生成客户端请求 —— 今天不讲,下节课讲

  • 相关阅读:
    java.lang.NoSuchMethodError:antlr.collections.AST.getLine() I
    T7 java Web day01 标签HTML
    T6 s1 day19
    T5 s5 Day18
    T5 s4 Day 17
    T5 s3 day16
    T5 s2 Day 15
    T5 s1 day14
    T4 S03 day 12
    T4 S01 day1
  • 原文地址:https://www.cnblogs.com/cx2016/p/13166525.html
Copyright © 2011-2022 走看看