声明:文中知识体系目录来自 dva.js 知识导图
本文阅读时间大概为 5 分钟,但是能让你了解基于 umi 和 dva 构建项目的最小知识体系,你可以粗略的浏览一下本文所提到的知识,在后续的讲解中都会多次重复提起,保证学习效率。
由于现在前端工程化的流行,所以在学习一个新的框架时,可能会面临一些疑惑。
拿 react 举例:
- es6 特性好多啊(es5 我都还没学完呢)
- component 有三种写法(茴字的四种写法了解一下)
- webpack 是什么(前端构建工具,然后呢,webpack是什么?)
- 什么同步异步数据流(我 callback 都理不清楚)
- …
ECMAScript 6
变量声明
const
用于声明常量,let
用于声明变量,他们都是块级作用域。
const a = 1;
let b = 1;
模板字符串
用于拼接字符串。
let a = 'hello';
let b = 'hello';
console.log('print:' + a + b);
let c = `print:${a}${b}`
// 注意这个不是引号,键盘 esc 下面那个按键
默认参数
function test(a = 'world') {
console.log(`print:hello,${a}`);
}
test();
// print:hello,world
箭头函数
函数的简化写法。
function test(a = 'world') {
console.log(`print:hello,${a}`);
}
const test = (a = 'world') => {
console.log(`print:hello,${a}`);
};
模块的导入和导出
// 从 antd 中导入按钮组件
import { Button } from 'antd';
// 导出一个方法,这样就能在其他文件使用 `import` 导入使用了
const test = (a = 'world') => {
console.log(`print:hello,${a}`);
};
export default test;
析构赋值
const obj = { key: 'umi', author: 'sorrycc' };
console.log(obj.key);
const { key } = obj;
// 等价于 `const key = obj.key;`
const obj2 = { key };
// 等价于 `const obj2 = { key: key };`;
// 数组也有类似的用法
const arr = [1, 2];
const [foo, bar] = arr;
console.log(foo);
// 1
展开运算符
用于数组组装:
const arr = ['umi'];
const texts = [...arr, 'dva'];
// texts => ['umi', 'dva']
用于取出数组部分属性:
const arr = ['umi', 'dva', 'antd'];
const [umi, ...other] = arr;
// 前面已经提过析构赋值,所以第一项会赋值给 `umi`,剩下的会被组合成一个 `other` 数组
console.log(umi);
// umi
console.log(other);
// (2)['dva', 'antd']
用于组合新的对象,key 相同时,靠后展开的值会覆盖靠前的值:
const obj = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const obj3 = { ...obj, ...obj2 };
// obj3 => { a: 1, b: 3, c: 4 }
JSX
组件嵌套
类似 html 。
<app>
<Header />
<Footer />
</app>
className
class
是 Javascript 的保留词,所以添加样式类名时,需用 className
代替 class
。
<h1 className="fancy">Hello Umi</h1>
JavaScript 表达式
JavaScript 表达式需要用 {}
括起来,会执行并返回结果。
<h1>{this.props.title}</h1>
注释
尽量不要使用 //
做单行注释。
<h1>
{/* multiline comment */}
{/*
multi
line
comment
*/}
{
// single line
}
Hello
</h1>
理解 CSS Modules
示例:
import styles from './example.css';
const Example = (<button className={styles.button}>Click me</button>);
/**
* .button {
* background-color: #1890ff;
* }
*/
你不必理解 CSS Modules 的工作原理,只需要知道 import from
使得被引用的样式文件可以只作用在引用它的地方,而不会全局生效。例如上述示例的 styles.button
在构建之后可能会被重命名为 ProductList_button_1FU0u
,而不再是 button
; ProductList_button_1FU0u
是全局生效的,而 styles.button
只在当前文件有效。这样,你可以为样式类名起一个简短的描述性名字,而不需要关心命名冲突问题。
Dva
Model
在 umi 项目中,你可以使用 dva 来处理数据流,以响应一些复杂的交互操作。这些处理数据流的文件统一放在 models 文件夹下,每一个文件默认导出一个对象,里面包含数据和处理数据的方法,通常我们称之为 model 。一个 model 文件的结构一般是这样的:
export default {
namespace: 'example', // 这个 model 的名字,必须全局唯一
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' });
}
});
},
},
(model,page和其他)
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);
以上内容,几乎包括了所有我们在实际项目中会使用到的所有知识。 需要强调的是,文中内容仅仅是我为了让大家便于理解,做了一些简化描述。 相关概念,大家可以在对 umi 稍微熟悉之后,参阅官方文档。
声明:文中知识体系目录来自开源项目:dva.js知识导图
—————————————————————————————————————————————————
原文链接:https://www.yuque.com/umijs/umi