umi.js 使用方法
node 环境安装
在官网下载与系统相应的 node 版本,node.js 版本 >=8.10
编辑器
推荐使用 Visual Studio Code 安装方法
安装 umi
npm install -g umi
推荐使用 yarn 代替 npm 来安装 umi,yarn 会针对部分场景做一些缓存以节省时间,你可以输入以下命令来全局安装 yarn,使用 yarn 后项目中尽量避免再使用 npm,不然可能会发生意想不到的错误。
npm install -g yarn
# 安装完成后,使用命令查看是否安装成功
yarn -v
# 使用 yarn 安装 umi
yarn global add umi
# 安装完成后,使用命令查看是否安装成功
umi -v
umi 快速搭建项目
创建项目文件后使用终端工具打开文件
推荐使用 yarn create 命令,能确保每次使用最新的脚手架。
yarn create umi / npm create umi
如果提示 create-umi 命令不存在,你需要执行 yarn global bin,然后把 global bin 的路径添加到环境变量 PATH 中。
选择 project, 选择 app 项目回车键确认
? Select the boilerplate type (Use arrow keys)
ant-design-pro – Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
❯ app – Create project with a simple boilerplate, support typescript.
block – Create a umi block.
library – Create a library with umi.
plugin – Create a umi plugin.
选择是否使用 TypeScript, 推荐使用 TypeScript,输入 y 后回车结束
? Do you want to use typescript? (y/N)
选择你需要的功能
功能介绍详见 plugin/umi-plugin-react
? What functionality do you want to enable? (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ antd
◯ dva
◯ code splitting
◯ dll
项目创建完成
启动项目
yarn start / npm run start
环境配置
在.env 文件中可更改环境配置,一般不需要更改,常见更改例如
# 更改服务启动端口号
PORT=8001
# 关闭自动打开浏览器,默认为打开
BROWSER=none
详细配置
config 配置
编译时的配置文件,.umirc.(js|ts) 和 config/config.(js|ts),二者选一,不可共存推荐在主文件夹下创建 config 文件,使用 config.js 进行项目配置(删除自动搭建项目时创建的.umirc.(js|ts))详细配置 config.local.js 和 config.production.js 可在此配置开发环境和线上环境不同的配置,在进行打包时需修改 package.json 中脚本代码
# 下载 cross-env 开启代码分割功能
yarn add -D cross-env / npm install –save-dev cross-env
# package.json 中 “scripts” 修改
“build”: “cross-env UMI_ENV=production umi build”
typings.d.ts 配置 (使用 typescript)
根据实际情况进行后缀添加,否则 ts 会报导入错误
declare module “*.png”;
declare module “*.jpg”;
declare module ‘*.less’;
tslint.yml 配置 (使用 typescript)
修改 tslint 规则,可根据个人使用情况修改,详细配置可见 tslint-react 相关约定规则
# 推荐修改
rules:
eofline: true
no-console: true
no-construct: true
no-debugger: true
no-reference: true
no-trailing-whitespace: false
jsx-no-multiline-js: false
jsx-alignment: false
jsx-no-lambda: false
(js|ts)config.json 开启 ES7 装饰器功能
“experimentalDecorators”: true
文件详解
mock 文件
存放 mock.js,默认开启 mock 功能,可在.env 文件中关闭:MOCK=none
src
所有与项目相关代码存放在 src 文件之中
src/assets
存放静态资源,例如图片文件、字体文件等
src/components
存放全局通用组件
src/layouts
全局布局,如果该文件夹下有 index.(js|tsx) 会在所有路由外面嵌套一层路由例如之前路由为
[
{path: ‘/’, component: ‘./pages/index’},
{path: ‘/users’, component: ‘./pages/users’},
]
嵌套之后为
[
{path: ‘/’, component: ‘./layouts/index’, routes: [
{path: ‘/’, component: ‘./pages/index’},
{path: ‘/users’, component: ‘./pages/users’},
] }
]
可在 index 文件中进行全局布局,或者根据 pathname 修改不同路由下的布局
src/models
全局 models, 如果有一个以上的页面会使用相同 namespace 空间内的代码,请将 models 文件放在此处,不然两个页面之间做交互时,namespace 中的代码会产生影响
src/styles
存放通用样式,如果想覆盖全局样式可在 global.(css|less|sass|scss) 进行修改,此文件不走 css modules,且会自动被引入。或者在 app.(js|ts) 中导入样式文件
src/services
存放全局通用请求
src/utils
存放通用方法
src/pages/.umi
这是 umi dev 时生产的临时目录,默认包含 umi.js 和 router.js,有些插件也会在这里生成一些其他临时文件。可以在这里做一些验证,但请不要直接在这里修改代码,umi 重启或者 pages 下的文件修改都会重新生成这个文件夹下的文件。该文件下的 router.js 可查看自动生成的路由
src/pages/…
项目页面文件,在不同文件中创建的 components、models、services 文件最好只在该页面中使用,可使项目结构变得更加清晰
tests
该文件为测试脚本文件,不会生成路由配置,如果需要使用 mock 测试,可以在外部 mock 文件中或者在该文件下创建__mock__文件
Dva.js 使用需掌握的知识点
Model
在 umi 项目中,你可以使用 dva 来处理数据流,以响应一些复杂的交互操作。这些处理数据流的文件统一放在 models 文件夹下,每一个文件默认导出一个对象,里面包含数据和处理数据的方法,通常我们称之为 model。一个 model 文件的结构一般是这样的:
export default {
namespace: ‘example’, // 这个 model 的名字,必须全局唯一, 否则相同 namespace 的代码会产生影响
state: {
count: 0,
}, // 初始数据
reducers: {
save() { …},
}, // 用于修改数据
effects: {
*getData() { …},
}, // 用于获取数据
subscriptions: {
setup() { …},
}, // 用于订阅数据
}
Reducer
每一个 reducer 都是一个普通函数,接受 state 和 action 作为参数,即:(state, action) => state,你可以在函数中更改旧的 state,返回新的 state。
reducers: {
save(state, { payload}) {
return ({…state, …payload});
},
},
Effect
每一个 effect 都是一个 生成器函数,你可以在这里获取你需要的数据,例如向服务器发起一个请求、或是获取其他 model 里的 state。为了明确分工,你无法在 effect 中直接修改 state,但你可以通过 put 方法 调用 reducer 来修改 state
state:{
assets:{},
},
*changeAssets({payload}, {call, put, select}) {
const user = yield select(states => states.user);
const assets = yield call(fetchData, user);
yield put({type: ‘save’, payload: { assets} });
},
select
此方法用于获取当前或其他 model 的 state。
const data = yield select(states => states[namespace]);
call
此方法用于执行一个异步函数,可以理解为等待这个函数执行结束。项目中常用于发送 http 请求,等待服务端响应数据。
const data = yield call(doSomethingFunc, parameter);
put
此方法用于触发一个 action,这个 action 既可以是一个 reducer 也可以是一个 effect。
yield put({type: ‘reducerName’, payload: { page} });
Subscription
subscription 用于订阅一个数据源,根据需要使用 dispatch 触发相应的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。项目中常用于页面初始化数据的自动请求,如:
subscriptions: {
setup({dispatch, history}) {
return history.listen(({pathname, query}) => {
// 进入 ‘/home’ 路由,发起一个名叫 ‘query’ 的 effect
if (pathname === ‘/home’) {
dispatch({type: ‘query’});
}
});
},
},
dispatch
类似 effect 中的 put 方法,你可以在 subscription 的参数、或是一个已经 connect 过的组件的 props 中拿到。
connect
通过此方法在你的组件中获取到指定 model 的 state 数据。
import {connect} from ‘dva’;
function App({user, dispatch}) {
const handleClick = () => {
dispatch({type: ‘user/fetchUser’});
};
return (
<div>
<h2>Hello, {user}</h2>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default connect(({user}) => ({user}))(App);
如果使用 es7 的装饰器则为
import {connect} from ‘dva’;
@connect(({user}) => ({user}))
function App({user, dispatch}) {
const handleClick = () => {
dispatch({type: ‘user/fetchUser’});
};
return (
<div>
<h2>Hello, {user}</h2>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default App;