声明:文中知识体系目录来自 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);// umiconsole.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 */}{/*multilinecomment*/}{// 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' 的 effectif (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
