快捷搜索: 长连接 前端 源码 pan

UmiJS基础&UmiJS+Dva

Umi,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。

1️⃣了解Umi

你可以将Umi简单的理解为一个专注性能的类 next.js 前端框架,并通过约定、自动生成和解析代码等方式来辅助开发,减少我们开发者的代码量。

功能特点

    开箱即用,Umi 内置了路由、构建、部署、测试等,仅需一个依赖即可上手开发。 完善的插件体系,Umi 实现了完整的生命周期,并使其插件化。此外还提供针对 React 的集成插件集。 完备路由,同时支持配置式路由和约定式路由,同时保持功能的完备性,比如动态路由、嵌套路由、权限路由等等。

技术收敛

蚂蚁金服前端框架 Umi把大家常用的技术栈进行整理,收敛到一起,让大家只用 Umi 就可以完成 80% 的日常工作。 Bigfish 企业级前端开发框架,与常见的前端框架和工具不同,它从工程角度集成了各类功能,从初始化开发到最终上线整套技术方案,解决了前端开发经常遇到的前端技术栈整合配置麻烦、开发联调麻烦、前端资源发布上线麻烦三大痛点。

创建第一个Umi应用

# 使用 yarn 管理 npm 依赖 使用国内源 之后使用tyarn代替yarn即可
$ npm i yarn tyarn -g

# 创建目录
$ mkdir myapp 

# 进入目录
$ cd myapp

# 通过官方工具创建项目
$ yarn create @umijs/umi-app

# 安装依赖
$ yarn

# 启动开发
$ yarn start

启动页面效果 和 当前项目结构

.umi 临时文件

.umi 临时目录是整个 Umi 项目的发动机,你的入口文件、路由等等都在这里,这些是由 umi 内部插件及三方插件生成的。

+ .umi
  + core     # 内部插件生成
  + pluginA  # 外部插件生成
  + presetB  # 外部插件生成
  + umi.ts   # 入口文件

临时文件是 Umi 框架中非常重要的一部分,框架或插件会根据你的代码生成临时文件,这些原来需要放在项目里的脏乱差的部分都被藏在了这里。

你可以在这里调试代码,但不要在 .git 仓库里提交他,因为他的临时性,每次启动 umi 时都会被删除并重新生成。

修改配置换个页面布局

默认的脚手架内置了 @umijs/preset-react,包含布局、权限、国际化、dva、简易数据流等常用功能。

想使用 ant-design-pro 的布局

  1. 添加@ant-design/pro-layout依赖
yarm add @ant-design/pro-layout
  1. 编辑 .umirc.ts文件,加入布局配置项 +layout:{},
import {
          
    defineConfig } from umi;

export default defineConfig({
          
   
  nodeModulesTransform: {
          
   
    type: none,
  },
  layout:{
          
   },
  routes: [
    {
          
    path: /, component: @/pages/index },
  ],
  fastRefresh: {
          
   },
});

部署发布

📌构建

$ yarn build

构建产物默认生成到 ./dist 下 📌本地验证 发布之前,可以通过 serve 做本地验证,

# 安装serve服务
npm i serve -g

# 启动发布的项目包
serve ./dist

访问 http://localhost:5000,正常情况下应该是和执行 yarn start 时是一致的。

2️⃣Umi基础

目录结构

一个基础的 Umi 项目大致是这样的

.
├── package.json		包含插件和插件集
├── .umirc.ts			配置文件,包含 umi 内置功能和插件的配置。
├── .env				环境变量。比如:PORT=8888
├── dist				打包产物默认会存放在这里。
├── mock				存储 mock 文件,此目录下所有 js 和 ts 文件会被解析为 mock 文件。
├── public				此目录下所有文件会被 copy 到输出路径。
├── config				项目复杂时候独立出来的的子配置文件,比如:routes.ts
└── src
    ├── .umi			临时文件目录,比如入口文件、路由等,都会被临时生成到这里。
    ├── layouts/index.tsx          约定式路由时的全局布局文件。
    ├── pages			所有路由组件存放在这里。
        ├── index.less
        └── index.tsx
    └── app.ts			运行时配置文件,可以在这里扩展运行时的能力,比如修改路由、修改 render 方法等。

配置

Umi 在 .umirc.ts 中配置项目和插件,支持 es6。一份常见的配置如下,

export default {
          
   
  base: /docs/,
  publicPath: /static/,
  hash: true,
  history: {
          
   
    type: hash,
  },
}

👉

defineConfig 让配置有代码提示

使用defineConfig方法可以让我们在写配置的时候有代码提示

import {
          
    defineConfig } from umi;

export default defineConfig({
          
   
  routes: [
    {
          
    path: /, component: @/pages/index },
  ],
});

本地临时配置

可以新建 .umirc.local.ts,这份配置会和 .umirc.ts 做 deep merge 后形成最终配置。

注:.umirc.local.ts 仅在 umi dev 时有效。umi build 时不会被加载。

// .umirc.ts 
export default {
          
    a: 1, b: 2 };

// .umirc.local.ts
export default {
          
    b: 3,c: local };

拿到的配置是:

{
          
   
  a: 1,
  b: 3,
  c: local,
}
    .local.ts 是本地验证使用的临时配置,请将其添加到 .gitignore,务必不要提交到 git 仓库中 .local.ts 配置的优先级最高,比 UMI_ENV 指定的配置更高

多环境多份配置

可以通过环境变量 UMI_ENV 区分不同环境来指定配置。

// .umirc.js 或者 config/config.js
export default {
          
    a: 1, b: 2 };

// .umirc.cloud.js 或者 config/config.cloud.js
export default {
          
    b: cloud, c: cloud };

// .umirc.local.js 或者 config/config.local.js
export default {
          
    c: local };

不指定 UMI_ENV 时,拿到的配置是:

{
          
   
  a: 1,
  b: 2,
  c: local,
}

指定 UMI_ENV=cloud 时,拿到的配置是:

{
          
   
  a: 1,
  b: cloud,
  c: cloud,
}

📌如何指定UMI_ENV? 在.env文件配置

运行时配置

运行时配置和配置的区别是前者跑在浏览器端而后者是在服务器端,所以运行时配置:

    不需要引入 node 依赖 可以写函数、jsx、import 浏览器端依赖

配置方式

约定(俗成) src/app.tsx 为运行时配置。在 src/app.ts 中你可以配置一些运行时的配置项来实现部分自定义需求。

📌 request 运行时配置示例:

import {
          
    RequestConfig } from umi;

export const request: RequestConfig = {
          
   
  timeout: 1000,
  errorConfig: {
          
   },
  middlewares: [],
  requestInterceptors: [],
  responseInterceptors: [],
};

📌dva 运行时配置示例:

import {
          
    createLogger } from redux-logger;
import {
          
    message } from antd;

export const dva = {
          
   
  config: {
          
   
    onAction: createLogger(),
    onError(e: Error) {
          
   
      message.error(e.message, 3);
    },
  },
};

路由

在 Umi 中,应用都是单页应用,页面地址的跳转都是在浏览器端完成的,不会重新请求服务端获取 html,html只在应用初始化时加载一次。所有页面由不同的组件构成,页面的切换其实就是不同组件的切换,你只需要在配置中把不同的路由路径和对应的组件关联上。

配置路由

在配置文件中进行配置,格式为路由信息的数组。

// config/routes.tsx
export default [
  {
          
    exact: true, path: /, component: index },
  {
          
    exact: true, path: /user, component: user },
  ]

📌 path   [Type: `string` ]

也可以是路径正则表达式


📌 component  [Type: string ]

配置 location 和 path 匹配后用于渲染的 React 组件路径。可以是绝对路径,也可以是相对路径,如果是相对路径,会从 src/pages 开始找起。

如果指向 src 目录的文件,可以用 @,也可以用 ../。比如 component: @/layouts/basic,或者 component: ../layouts/basic,推荐用前者。


📌 exact  [Type: `boolean` Default: `true`]

表示是否严格匹配,即 location 是否和 path 完全对应上。

export default {
          
   
  routes: [
    // url 为 /one/two 时匹配失败
    {
          
    path: /one, exact: true },
    
    // url 为 /one/two 时匹配成功
    {
          
    path: /one },
    {
          
    path: /one, exact: false },
  ],
}

📌 routes

配置子路由,通常在需要为多个路径增加 layout 组件时使用。

// config/routes.tsx
export default [
  {
          
   
    path: /ex, component: @/pages/layouts, routes: [
      {
          
    path: /ex/list, component: @/pages/list },
      {
          
    path: /ex/admin, component: @/pages/admin }
    ]
  },
]

然后在 src/layouts/index 中通过 props.children 渲染子路由,

// src/layouts/index.tsx
export default (props)=>{
          
   
    return <>{
          
   props.children}</>
}

这样,访问 /ex/list 和 /ex/admin 就会带上 src/layouts/index 这个 layout 组件。

// src/pages/list.tsx
export default function list(){
          
   
    return (<h1>list</h1>);
}
// src/pages/admin.tsx
export default function admin(){
          
   
    return (<h1>admin</h1>);
}

📌 redirect  [Type: string ]

配置路由跳转。

export default [
  {
          
    exact: true, path: /, redirect: /list },
  {
          
    exact: true, path: /list, component: @/pages/list }
]

访问 / 会跳转到 /list,并由 src/pages/list 文件进行渲染。


📌 wrappers [Type: string[] ]

配置路由的高阶组件封装。

比如,可以用于路由级别的权限校验:

export default {
          
   
  routes: [
    {
          
    path: /user, component: user,
      wrappers: [
        @/wrappers/auth,
      ],
    },
    {
          
    path: /login, component: login },
  ]
}

然后在 src/wrappers/auth 中,

import {
          
    Redirect } from umi

export default (props) => {
          
   
  const {
          
    isLogin } = useAuth();
  if (isLogin) {
          
   
    return <div>{
          
    props.children }</div>;
  } else {
          
   
    return <Redirect to="/login" />;
  }
}

这样,访问 /user,就通过 useAuth 做权限校验,如果通过,渲染 src/pages/user,否则跳转到 /login,由 src/pages/login 进行渲染。


📌 title [Type: string[] ]

配置路由的标题。

页面跳转

命令式页面跳转:通过 history 使用,通常在事件处理中被调用。

import {
          
    history } from umi;

// 跳转到指定路由
history.push(/list);

// 带参数跳转到指定路由
history.push(/list?a=b);
history.push({
          
   
  pathname: /list,
  query: {
          
   
    a: b,
  },
});

// 跳转到上一个路由
history.goBack();

Link 组件

声明式页面跳转

import {
          
    Link } from umi;

export default () => (
  <div>
    <Link to="/users">Users Page</Link>
  </div>
);

Link 只用于单页应用的内部跳转,如果是外部地址跳转请使用 a 标签

约定式路由

约定式路由也叫文件路由,就是不需要手写配置,文件系统即路由,通过目录和文件及其命名分析出路由配置。

如果没有 routes 配置,Umi 会进入约定式路由模式,然后分析 src/pages 目录拿到路由配置。

└── pages
    ├── index.tsx
    └── users.tsx

会得到以下路由配置,

[
  {
          
    exact: true, path: /, component: @/pages/index },
  {
          
    exact: true, path: /users, component: @/pages/users },
]

满足以下任意规则的文件不会被注册为路由,

    以 . 或 _ 开头的文件或目录 以 d.ts 结尾的类型定义文件 以 test.ts、spec.ts、e2e.ts 结尾的测试文件(适用于 .js、.jsx 和 .tsx 文件) components 和 component 目录 utils 和 util 目录 不是 .js、.jsx、.ts 或 .tsx 文件 文件内容不包含 JSX 元素

动态路由

约定 [] 包裹的文件或文件夹为动态路由。 比如:

    src/pages/users/[id].tsx 会成为 /users/:id src/pages/users/[id]/settings.tsx 会成为 /users/:id/settings

动态可选路由

约定 [ $] 包裹的文件或文件夹为动态可选路由。

比如:

    src/pages/users/[id$].tsx 会成为 /users/:id? src/pages/users/[id$]/settings.tsx 会成为 /users/:id?/settings

嵌套路由

Umi 里约定目录下有 _layout.tsx 时会生成嵌套路由,以 _layout.tsx 为该目录的 layout。layout文件需要返回一个 React 组件,并通过 props.children 渲染子组件。
// _layout.tsx
export default (props: {
          
    children: any })=>{
          
   
    return <>layout{
          
   props.children}</>
}

全局 layout

约定 src/layouts/index.tsx 为全局路由。返回一个 React 组件,并通过 props.children 渲染子组件。

export default (props: {
          
    children: any })=>{
          
   
  return <>
  <h1>全局</h1>
  {
          
   props.children}</>
}

不同的全局 layout

在 src/layouts/index.tsx 中对 location.path 做区分,渲染不同的 layout 。

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

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

404 路由

约定 src/pages/404.tsx 为 404 页面,需返回 React 组件。

权限路由

通过指定高阶组件 wrappers 达成效果

如下,src/pages/user:

import React from react

function User() {
          
   
  return <>user profile</>
}

User.wrappers = [@/wrappers/auth]

export default User

然后在 src/wrappers/auth 中,

import {
          
    Redirect } from umi

export default (props) => {
          
   
  const {
          
    isLogin } = useAuth();
  if (isLogin) {
          
   
    return <div>{
          
    props.children }</div>;
  } else {
          
   
    return <Redirect to="/login" />;
  }
}

这样,访问 /user,就通过 useAuth 做权限校验,如果通过,渲染 src/pages/user,否则跳转到 /login,由 src/pages/login 进行渲染。

插件

📌插件的 id 和 key

每个插件都会对应一个 id 和一个 key,id 是路径的简写,key 是进一步简化后用于配置的唯一值。

比如插件 /node_modules/@umijs/plugin-foo/index.js,通常来说,其 id 为 @umijs/plugin-foo,key 为 foo。

启用插件

📌package.json 依赖

Umi 会自动检测 dependencies 和 devDependencies 里的 umi 插件,比如:

{
          
   
  "dependencies": {
          
   
    "@umijs/preset-react": "1"
  }
}

那么 @umijs/preset-react 会自动被注册,无需在配置里重复声明。

📌配置 .umirc.ts

在配置里可通过 presets 和 plugins 配置插件,比如:

export default {
          
   
  presets: [./preset, foo/presets],
  plugins: [./plugin],
}

禁用插件

📌配置 key 为 false

export default {
          
   
  mock: false,
}

检查插件注册情况

$ umi plugin list

# 顺便看看他们分别用了哪些 key
$ umi plugin list --key

拓展:按需加载插件

常见使用场景:组件体积太大,不适合直接计入 bundle 中,以免影响首屏加载速度。例如:某组件 HugeA 包含巨大的实现 / 依赖了巨大的三方库,且该组件 HugeA 的使用不在首屏显示范围内,可被单独拆出。这时候,dynamic 就该上场了

启用按需加载

按需加载功能默认是关闭的,需要通过配置开启

export default {
          
   
  dynamicImport: {
          
   },
}

使用按需加载

dynamic是一个按需加载组件,封装了使用一个异步组件需要做的状态维护工作

📌封装一个异步组件

//AsyncHugeA.tsx
import {
          
    dynamic } from umi;

export default dynamic({
          
   
  loader: async function() {
          
   
    // 这里的注释 webpackChunkName 可以指导 webpack 将该组件 HugeA 以这个名字单独拆出去
    const {
          
    default: HugeA } = await import(/* webpackChunkName: "external_A" */ ./HugeA);
    return HugeA;
  },
});

📌使用异步组件

import React from react;
import AsyncHugeA from ./AsyncHugeA;

// 像使用普通组件一样即可
// dynamic 为你做:
// 1. 异步加载该模块的 bundle
// 2. 加载期间 显示 loading(可定制)
// 3. 异步组件加载完毕后,显示异步组件
export default () => {
          
   
  return <AsyncHugeA />;
}

HTML模板

修改默认模板

新建 src/pages/document.ejs,umi 约定如果这个文件存在,会作为默认模板,比如

<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Your App</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

修改title,直接在.umirc.ts加入title配置项即可

配置模板

模板里可通过 context 来获取到 umi 提供的变量,context 包含:

    route,路由信息,需要打包出多个静态 HTML 时(即配置了 exportStatic 时)有效 config,用户配置信息 .umirc.ts
<link rel="icon" type="image/x-icon" href="<%= context.config.publicPath %>favicon.png" />

Mock 数据

约定式 Mock 文件

Umi 约定 /mock 文件夹下所有文件为 mock 文件。

.
├── mock
    ├── api.ts
    └── users.ts

/mock 下的 api.ts 和 users.ts 会被解析为 mock 文件。

编写 Mock 文件

requestType requestPath:response

如 /mock/api.ts 的内容如下,

export default {
          
   
  // 支持值为 Object 和 Array
  GET /api/users: {
          
    users: [1, 2] },

  // GET 可忽略
  /api/users/1: {
          
    id: 1 },

  // 支持自定义函数,API 参考 express@4
  POST /api/users/create: (req, res) => {
          
   
    // 添加跨域请求头
    res.setHeader(Access-Control-Allow-Origin, *);
    res.end(ok);
  },
}

引入 Mock.js

yarn add @types/mockjs -D
import mockjs from mockjs;

export default {
          
   
  // 使用 mockjs 等三方库
  GET /api/tags: mockjs.mock({
          
   
    list|100: [{
          
    name: @city, value|1-100: 50, type|0-2: 1 }],
  }),
};

常用的环境变量

Umi 中约定根目录下的 .env 为环境变量配置文件。通过key=value配置

//.env
PORT=3000 
HTTPS=1

ANALYZE

用于分析 bundle 构成,默认关闭。

ANALYZE=1

FORK_TS_CHECKER

默认不开启 TypeScript 类型检查,值为 1 时启用。比如:

FORK_TS_CHECKER=1

HTTPS

localhost 开启 https

HTTPS=1

同时也可以使用配置 https: { key: /path/key.pem, cert: /path/cert.pem } 自定义证书。

PORT

指定端口号,默认是 8000。

UMI_ENV

指定不同环境各自的配置文件

UMI_ENV=cloud
// .umirc.js 
export default {
          
    a: 1, b: 2 };

// .umirc.cloud.js 
export default {
          
    b: cloud, c: cloud };

// .umirc.local.js 
export default {
          
    c: local };

指定 UMI_ENV=cloud 时,拿到的配置是:

{
          
   
  a: 1,
  b: cloud,
  c: cloud,
}

3️⃣样式和资源文件

以下虽然使用.css示例,写成.less效果一样

使用 CSS

Umi 内置支持 less,不支持 sass 和 stylus,但如果有需求,可以通过 chainWebpack 配置或者 umi 插件的形式支持。

全局样式

Umi 中约定 src/global.css 为全局样式,如果存在此文件,会被自动引入到入口文件最前面。

CSS Modules

Umi 会自动识别 CSS Modules 的使用,你把他当做 CSS Modules 用时才是 CSS Modules。

// CSS Modules
import styles from ./foo.css;

// 非 CSS Modules
import ./foo.css;

使用图片

JS 里使用图片

import logoSrc from ./logo.svg

 <img src={
          
   http://www.ivotoo.com/test/1.jpg}/>
 <img src={
          
   require(../../public/images/1.jpeg)}/>
 <img src={
          
   logoSrc} />

//支持别名,比如通过 @ 指向 src 目录:
<img src={
          
   require(@/foo.png)} />

如果是svg类型,还可以组件式引入:

import {
          
    ReactComponent as Logo } from ./logo.svg

function Analysis() {
          
   
  return <Logo width={
          
   90} height={
          
   120} />
}

CSS 里使用图片

通过相对路径引用:

.logo {
          
   
  background: url(./foo.png);
}

CSS 里也支持别名,但需要在前面加 ~ 前缀:

.logo {
          
   
  background: url(~@/foo.png);
}

图片路径问题

项目中使用图片有两种方式,

    先把图片传到 cdn,然后在 JS 和 CSS 中使用图片的绝对路径 把图片放在项目里,然后在 JS 和 CSS 中通过相对路径的方式使用

前者不会有任何问题;后者,如果在 JS 中引用相对路径的图片时,在发布时会根据 publicPath 引入绝对路径,所以就算没有开启 dynamicImport 时,也需要注意 publicPath 的正确性。

Base64 编译

通过相对路径引入图片的时候,如果图片小于 10K,会被编译为 Base64,否则会被构建为独立的图片文件。

10K 这个阈值可以通过 inlineLimit 配置修改。

4️⃣Umi进阶

使用dva models

我们在创建项目的时候引入了@umijs/preset-react ,这是一个插件集,包含:

    plugin-access,权限管理 plugin-analytics,统计管理 plugin-antd,整合 antd UI 组件 plugin-crossorigin,通常用于 JS 出错统计 plugin-dva,整合 dva plugin-helmet,整合 react-helmet,管理 HTML 文档标签(如标题、描述等) plugin-initial-state,初始化数据管理 plugin-layout,配置启用 ant-design-pro 的布局 plugin-locale,国际化能力 plugin-model,基于 hooks 的简易数据流 plugin-request,基于 umi-request 和 umi-hooks 的请求方案

所以无需再而外安装 plugin-dva ,至于以上插件的用法,看

开启dva

dva 配置有没有开启,该插件是配置开启的 只需要在配置中开启即可。打开 umi 的配置文件:

//.umirc.js
import {
          
    defineConfig } from umi;

export default defineConfig({
          
   
  dva: {
          
   },
  antd: {
          
   }
});

新增 model 文件

约定式的 model 组织方式
符合以下规则的文件会被认为是 model 文件,

src/models 下的文件
src/pages 下,子目录中 models 目录下的文件
src/pages 下,所有 model.ts 文件

比如:
+ src
  + models/a.ts
  + pages
    + foo/models/b.ts
    + bar/model.ts
其中 a.ts,b.ts 和 model.ts 如果其内容是有效 dva model 写法,则会被认为是 model 文件。
// src/models/hero.ts
import {
          
    Effect, Reducer } from umi;

export interface HeroModelState {
          
   
  name: string;
}

export interface HeroModelType {
          
   
  namespace: hero;
  state: HeroModelState;
  effects: {
          
   
    query: Effect;
  };
  reducers: {
          
   
    save: Reducer<HeroModelState>;
  };
}

const HeroModel: HeroModelType = {
          
   
  namespace: hero,

  state: {
          
   
    name: hero,
  },

  effects: {
          
   
    *query({
          
    payload }, {
          
    call, put }) {
          
   

    },
  },
  reducers: {
          
   
    save(state, action) {
          
   
      return {
          
   
        ...state,
        ...action.payload,
      };
    },
  },
};

export default HeroModel;

如果文件中的 namespace 未写明,umi 会使用文件名作为 model 的 namespace。为了减少错误的出现,最好保持所有的 model 文件,文件名不同。

在页面中使用model

// src/pages/hero.tsx

import React, {
          
    FC } from react;
import styles from ./hero.css;
import {
          
    connect, HeroModelState, ConnectProps } from umi;  ---step1


interface PageProps extends ConnectProps {
          
   
  hero: HeroModelState;
}

const Hero: FC<PageProps> = (props) => {
          
            ---step2
  console.log(props.hero);      ---step4
  return (
    <div>
      <h1 className={
          
   styles.title}>Page hero</h1>
      <h2>This is {
          
   props.hero.name}</h2>
    </div>
  );
}
export default connect(({
          
    hero }: {
          
    hero: HeroModelState }) => ({
          
    hero }))(Hero);
  --- step3
    step1 在文件头部引入了 umi 的connect,HeroModelState, ConnectProps step2 把之前的匿名函数,改成实名函数Hero step3 使用connect连接页面和models step4 从属性中取出namespace为hero的model的state数据。

监听路由事件

进入页面的时候,发起请求页面初始化数据。这里我们通过 dva model 的 subscriptions 实现。

src/models/hero.ts subscriptions

import {
          
    Effect, Reducer, Subscription } from umi;

export interface HeroModelType {
          
   
  namespace: hero;
  state: HeroModelState;
  effects: {
          
   
    query: Effect;
  };
  reducers: {
          
   
    save: Reducer<HeroModelState>;
  };
+  subscriptions: {
          
    setup: Subscription };
}
HeroModel 中增加 subscriptions
subscriptions: {
          
   
        setup({
          
    dispatch, history }) {
          
   
            return history.listen(({
          
    pathname, query }) => {
          
   
                if (pathname === /hero) {
          
   
                    dispatch({
          
   
                        type: fetch
                    })
                }
            });
        }
    },

这里需要注意的是,subscriptions 是一个全局的监听,就是说,当设定触发条件满足时,所有的 subscriptions 都会响应,所以我们在这里判断了路由为当前路由时,发起一个 effects 事件。

proxy 请求代理

之所以会出现跨域访问问题,是因为浏览器的安全策略。所以我们预想是不是有一种方式,能够绕过浏览器的安全策略?

那就是先请求一个同源服务器,再由服务器去请求其他的服务器。比如:

配置 proxy

    step1 设置了需要代理的请求头,比如这里定义了 /api ,当你访问如 /api/abc 这样子的请求,就会触发代理 step2 设置代理的目标,即真实的服务器地址 changeOrigin 设置是否跨域请求资源 pathRewrite 表示是否重写请求地址,比如这里的配置,就是把 /api 替换成空字符

src/app.ts

=========================================================================

本文简单学习了umi,更深层次学习还需要大家查看官网与部分。如有不足,还望指出。

参考文档:

经验分享 程序员 微信小程序 职场和发展