umijs / umi

A framework in react community ✨

Home Page:https://umijs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

开发中遇到的问题,已经处理的,在这里记录一下。给朋友们一个参考

xiaohuoni opened this issue · comments

现在文档比较少,好几个朋友都遇到一样的问题,在这里记录一下。大家还有遇到什么问题,可以在这里补充,我会尽量帮忙搞到解决方案

在ejs里面增加viewport会导致hd方案失效

注意initial-scale=1 会导致失效,可以使用以下的mate

<meta name="viewport" content="width=device-width,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">

局部覆盖antd 样式

.wrapper {
    height: 500px;
     :global {
        .am-button-text {
            padding: 6px;
        }
    }
}

使用浏览器返回,页面没有刷新

layouts/index.js 里用 withRouter 包以下。参考 https://github.com/umijs/umi-dva-user-dashboard/blob/master/src/layouts/index.js

使用withRouter和connect包裹Layout错误

export default withRouter(connect(({}) => ({}))(Layout))

注意先后顺序

build 后访问路由刷新后 404?

几个方案供选择:

* 改用 hashHistory,在 `.umirc.js` 里配 `hashHistory: true`
* 静态化,在 `.umirc.js` 里配 `exportStatic: true`
* 服务端配置路由 fallback  index.html

build的时候,图片路径报错

在webpackrc中配置publicPath:"/static/",

.umirc.mock.js

简单用法

export default {
  '/api/hello'(req, res) {
    res.end(`hello ${Math.random()}`);
  },
  ...require('./mock/user'),
};

可以用下面的方法,写到别的文件里面去。

const mock = {}
require('fs').readdirSync(require('path').join(__dirname + '/mock')).forEach(function(file) {
	Object.assign(mock, require('./mock/' + file))
})
module.exports = mock

document.ejs

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="format-detection" content="email=no" />
    <title></title>
</head>
<style>
    body{
        user-select:none;
    }
</style>
<body >

<div id="root"></div>
</body>

</html>

配置模板[https://umijs.org/docs/zh-Hans/html-tpl.html](配置 HTML 模板)

动态修改title

import { Helmet } from 'react-helmet';
<Helmet>
        <title>UMI DEMO</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="icon" href={xxx} type="image/x-icon" />
        <script src={xxx} />
        <link rel="stylesheet" href={xxx} />
      </Helmet>

在混合应用中,iOS修改不了。可以使用react-document-title

如何引入 polyfill?

先安装依赖,

$ npm install @babel/polyfill --save

新建 src/global.js,内容如下:

import '@babel/polyfill';

推荐使用umi-plugin-polyfill

build 后,打开只有标题 ,页面空白

页面需要部署
最简单的方式是
$npm i serve -g
在dist目录下
$ serve

this.setDynamic is not a function

将旧的roadhog或者dva项目,转移到umi时
如果有babel-runtime依赖和配置了babel-plugin-transform-runtime插件,需删除,因为已内置处理,

在request.js文件里有办法做路由跳转吗

路由跳转用这个
import router from 'umi/router';
router.push('/login')
抛事件用window.g_app._store.dispatch

在gobal.less中覆盖ant的样式

在开发环境下,有效。
build之后,发现ant的样式会覆盖写在gobal.less中的样式

暂时的处理是给样式强制 !important

有些页面不使用公共的Layout

config.js

const openPages: ['/login','/plan','/home',"/"];
module.exports = {
    openPages:openPages
}

layouts/index.js

import config  from "config.js";
const { openPages } = config;
if (openPages && openPages.includes(pathname)) {
    return (
      <div>
        {children}
      </div>
    );
  }else{
//something
}

锚点 和hashHistory冲突

import { HashLink } from "react-router-hash-link";
const router ="main";//当前的路由,重复跳转到当前路由不会触发页面更新
const anchorHref="#api";//这个是定位的锚点 如<div id="api"></div>
<HashLink to={`/${router}${anchorHref}`}>点击跳转</HashLink>

上述方法不好用,涉及到路由携带参数,会有问题。
使用下面方法

 handleQuickJump(id, e) {
    if (e) {
      e.preventDefault();
    }
    const node = document.querySelector(id);
    if (node) {
      node.scrollIntoView(true);
    }
  }

多层嵌套的State

习惯使用VUE的朋友(或其他别的框架使用者),对嵌套的state使用不习惯的。
方法1:使用Umi

export default {
  plugins: [
    ['umi-plugin-dva', { immer: true }],
  ],
};

方法2:自己写的react组件

$ npm install immer --save
import produce from "immer"
/**
 * Classic React.setState with a deep merge
 */
onBirthDayClick1 = () => {
    this.setState((prevState)=>({
        user: {
            ...prevState.user,
            age: prevState.user.age + 1
        }
    }))
}

/**
 * ...But, since setState accepts functions,
 * we can just create a curried producer and further simplify!
*/
onBirthDayClick2 = () => {
    this.setState(produce(draft => {
        draft.user.age += 1
    }))
}

用的组件都是immer

umi-antd-pro,现在的都是在antd-design-pro的基础上修改的,觉得有点乱,保留antd-design-pro的组件和页面逻辑,一点点整理的。地址:https://github.com/xiaohuoni/umi-antd-pro

脚手架

官方

umi-dva-user-dashboardUser dashboard example with combination use of umi and dva.
umi-antd-admin A admin dashboard application demo built upon Ant Design and Umi
with-dva umi with dva
with-dva-and-immer umi with dva and immer
umi-examples umi examples

非官方

umi-antd-pro umi-antd-pro,所有的组件和页面逻辑保留 Ant Design Pro的设计。
dva-umi a scaffolding for dva-umi (已在项目中使用)
dva-umi-mobile a scaffolding for dva-umi-mobile (已在项目中使用)
umi-pro 基于umi, 大部分代码重用 ant design pro 使用react-intl支持多语言 (已在项目中使用)

切换默认的'Compiling'

@sorrycc 你觉得怎么处理这个问题比较好哦?
1、在umirc.js中增加配置
2、增加一个Compiling.js返回一个react dom。目录层级和dva.js一起
我比较想用第二种方法,不知道还有没有别的方案

@xiaohuoni 很赞,这里面提到的问题,开发过程有很多都碰到过。

@chenfengyanyu 欢迎补充,后续让大佬把这里整理一下,可以放到FAQ里面。

@xiaohuoni 有遇到环境变量的问题嘛,我有几套环境,需要不同的API地址:

"release": "cross-env NODE_ENV=production umi build",
"dev": "cross-env NODE_ENV=development umi build",

像上面这样,只要我一运行 npm run dev,NODE_ENV 就会变成 production ,所以区分不了环境。不知道你是如何处理的?

如何在项目中使用图片

import React from 'react';
import logo from './logo.png'; // Tell Webpack this JS file uses this image

console.log(logo); // /logo.84287d09.png

function Header() {
  // Import result is the URL of your image
  return <img src={logo} alt="Logo" />;
}

export default Header;
.Logo {
  background-image: url(./logo.png);
}

@chenfengyanyu 我自己定义了一个环境变量SERVER=PROD SERVER=TEST

@daqi 谢谢啦,我也是换了环境变量

@xiaohuoni 大佬你好,请问一下,引入了@babel/polyfill之后会在Dvacontainer文件里报错,引入了umi-plugin-polyfill会报错缺少')',这个怎么才能解决

commented

@daqi 可以分享下怎么配置的吗~谢谢!

@axu6705

配置

package.json里面大概是这样

{
"scripts": {
    "start": "SERVER=dev umi dev",
    "build": "SERVER=prod umi build",
    "build:test": "SERVER=test umi build",
    "upload": "export SERVER=prod && node upload.js",
    "upload:test": "export SERVER=test && node upload.js"
  },
...
}

使用

config/index.js

let config = require('./'+process.env.SERVER+'.js')

module.exports = config

.webpackrc.js

const publicPath =
  process.env.SERVER === 'prod'
    ? 'http://img0.abc.com/abc-h5/'
    : process.env.SERVER === 'test' ? 'http://static.abc.com/abc-h5/' : '/static/'

export default {
  publicPath: publicPath
}

常见 FAQ 在 https://umijs.org/guide/faq.html 继续维护,可以提 PR 到这里。

@xiaohuoni 关于项目图标 https://juejin.im/post/59bb864b5188257e7a427c09 作者提供的方案感觉比较优雅,可否提供一个配置方案

参考 https://github.com/zuiidea/antd-admin 并做一些优化

具体步骤如下

1、 .webpackrc.js 作如下配置

urlLoaderExcludes: [
    path.join(__dirname, 'src/icons')
]

2、添加 webpack.config.js 文件(需添加svg-sprite-loader依赖)

const path = require('path');

export default function (webpackConfig) {
  webpackConfig.module.rules.push({
    test: /\.svg$/i,
    include: [path.join(__dirname, 'src/icons')],
    use: [
      {
        loader: require.resolve('svg-sprite-loader')
      }
    ]
  });

  return webpackConfig
};

3、添加svg文件

请在src/icons/svg 目录下添加svg文件

4、 新建src/icons/index.js

const requireAll = requireContext => requireContext.keys().map(requireContext);
const req = require.context('./svg', false, /\.svg$/);
requireAll(req);

5、在global.js 引入

import './icons/index';

6、新建SvgIcon组件

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ClassNames from 'classnames';
import styles from './index.less';

class Index extends Component {
  static propTypes = {
    className: PropTypes.string,
    icon: PropTypes.string
  };

  static defaultProps = {
    className: '',
    icon: ''
  };

  render() {
    const { className, icon } = this.props;
    const clsString = ClassNames(className, styles.main);

    return (
      <svg className={clsString} aria-hidden="true">
        <use xlinkHref={`#${icon}`} />
      </svg>
    )
  }
}

export default Index;

@chenfengyanyu 我自己定义了一个环境变量SERVER=PROD SERVER=TEST

是如何做到自己定义环境变量的呢?我自己定义过后,但是无法获取变量,无论如何都是undefined

@wangxingkang 感谢分享,今天才看到你的这个回复。

commented

请问有遇到过在layout中使用cloneelement给children传递方法,children获取undefined么

commented

请问有遇到过在layout中使用cloneelement给children传递方法,children获取undefined么

提供一下你的使用规则呗 这种问题一般都是react用法问题哦

@freedomljt 在umi中,layout的children并不是你的page,而是路由,所以你传递的属性并没有加入到你的页面中,你可以打印一下layout的children看看

这个太长了,打开浪费太多时间。有问题重发iss吧