# dva-knowledgemap **Repository Path**: devil13th/dva-knowledgemap ## Basic Information - **Project Name**: dva-knowledgemap - **Description**: Knowledge map for dva. - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-08-04 - **Last Updated**: 2021-08-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # dva.js 知识导图 - [Read "the dva.js Knowledgemap" in English](./README_en.md) - ["the dva.js Knowledgemap" 日本語版](./README_ja.md) > 注:如果你使用 dva@2,请先忽略这里的路由部分,待更新。 不知大家学 react 或 dva 时会不会有这样的疑惑: - es6 特性那么多,我需要全部学会吗? - react component 有 3 种写法,我需要全部学会吗? - reducer 的增删改应该怎么写? - 怎么做全局/局部的错误处理? - 怎么发异步请求? - 怎么处理复杂的异步业务逻辑? - 怎么配置路由? - ... 这篇文档梳理了基于 [dva-cli](https://github.com/dvajs/dva-cli) 使用 [dva](https://github.com/dvajs/dva) 的最小知识集,让你可以用最少的时间掌握创建类似 [dva-hackernews](https://github.com/dvajs/dva-hackernews) 的全部知识,并且不需要掌握额外的冗余知识。 ## 目录 * [JavaScript 语言](#javascript-语言) * [变量声明](#变量声明) * [const 和 let](#const-和-let) * [模板字符串](#模板字符串) * [默认参数](#默认参数) * [箭头函数](#箭头函数) * [模块的 Import 和 Export](#模块的-import-和-export) * [ES6 对象和数组](#es6-对象和数组) * [析构赋值](#析构赋值) * [对象字面量改进](#对象字面量改进) * [Spread Operator](#spread-operator) * [Promises](#promises) * [Generators](#generators) * [React Component](#react-component) * [Stateless Functional Components](#stateless-functional-components) * [JSX](#jsx) * [Component 嵌套](#component-嵌套) * [className](#classname) * [JavaScript 表达式](#javascript-表达式) * [Mapping Arrays to JSX](#mapping-arrays-to-jsx) * [注释](#注释) * [Spread Attributes](#spread-attributes) * [Props](#props) * [propTypes](#proptypes) * [往下传数据](#往下传数据) * [往上传数据](#往上传数据) * [CSS Modules](#css-modules) * [理解 CSS Modules](#理解-css-modules) * [定义全局 CSS](#定义全局-css) * [classnames Package](#classnames-package) * [Reducer](#reducer) * [增删改](#增删改) * [嵌套数据的增删改](#嵌套数据的增删改) * [Effect](#effect) * [Effects](#effects) * [put](#put) * [call](#call) * [select](#select) * [错误处理](#错误处理) * [全局错误处理](#全局错误处理) * [本地错误处理](#本地错误处理) * [异步请求](#异步请求) * [GET 和 POST](#get-和-post) * [统一错误处理](#统一错误处理) * [Subscription](#subscription) * [异步数据初始化](#异步数据初始化) * [path-to-regexp Package](#path-to-regexp-package) * [Router](#router) * [Config with JSX Element (router.js)](#config-with-jsx-element-routerjs) * [Route Components](#route-components) * [通过 connect 绑定数据](#通过-connect-绑定数据) * [Injected Props (e.g. location)](#injected-props-eg-location) * [基于 action 进行页面跳转](#基于-action-进行页面跳转) * [dva 配置](#dva-配置) * [Redux Middleware](#redux-middleware) * [history](#history) * [切换 history 为 browserHistory](#切换-history-为-browserhistory) * [去除 hashHistory 下的 _k 查询参数](#去除-hashhistory-下的-_k-查询参数) * [工具](#工具) * [通过 dva-cli 创建项目](#通过-dva-cli-创建项目) ## JavaScript 语言 ### 变量声明 #### const 和 let 不要用 `var`,而是用 `const` 和 `let`,分别表示常量和变量。不同于 `var` 的函数作用域,`const` 和 `let` 都是块级作用域。 ```javascript const DELAY = 1000; let count = 0; count = count + 1; ``` #### 模板字符串 模板字符串提供了另一种做字符串组合的方法。 ```javascript const user = 'world'; console.log(`hello ${user}`); // hello world // 多行 const content = ` Hello ${firstName}, Thanks for ordering ${qty} tickets to ${event}. `; ``` #### 默认参数 ```javascript function logActivity(activity = 'skiing') { console.log(activity); } logActivity(); // skiing ``` ### 箭头函数 函数的快捷写法,不需要通过 `function` 关键字创建函数,并且还可以省略 `return` 关键字。 同时,箭头函数还会继承当前上下文的 `this` 关键字。 比如: ```javascript [1, 2, 3].map(x => x + 1); // [2, 3, 4] ``` 等同于: ```javascript [1, 2, 3].map((function(x) { return x + 1; }).bind(this)); ``` ### 模块的 Import 和 Export `import` 用于引入模块,`export` 用于导出模块。 比如: ```javascript // 引入全部 import dva from 'dva'; // 引入部分 import { connect } from 'dva'; import { Link, Route } from 'dva/router'; // 引入全部并作为 github 对象 import * as github from './services/github'; // 导出默认 export default App; // 部分导出,需 import { App } from './file'; 引入 export class App extend Component {}; ``` ### ES6 对象和数组 #### 析构赋值 析构赋值让我们从 Object 或 Array 里取部分数据存为变量。 ```javascript // 对象 const user = { name: 'guanguan', age: 2 }; const { name, age } = user; console.log(`${name} : ${age}`); // guanguan : 2 // 数组 const arr = [1, 2]; const [foo, bar] = arr; console.log(foo); // 1 ``` 我们也可以析构传入的函数参数。 ```javascript const add = (state, { payload }) => { return state.concat(payload); }; ``` 析构时还可以配 alias,让代码更具有语义。 ```javascript const add = (state, { payload: todo }) => { return state.concat(todo); }; ``` #### 对象字面量改进 这是析构的反向操作,用于重新组织一个 Object 。 ```javascript const name = 'duoduo'; const age = 8; const user = { name, age }; // { name: 'duoduo', age: 8 } ``` 定义对象方法时,还可以省去 `function` 关键字。 ```javascript app.model({ reducers: { add() {} // 等同于 add: function() {} }, effects: { *addRemote() {} // 等同于 addRemote: function*() {} }, }); ``` #### Spread Operator Spread Operator 即 3 个点 `...`,有几种不同的使用方法。 可用于组装数组。 ```javascript const todos = ['Learn dva']; [...todos, 'Learn antd']; // ['Learn dva', 'Learn antd'] ``` 也可用于获取数组的部分项。 ```javascript const arr = ['a', 'b', 'c']; const [first, ...rest] = arr; rest; // ['b', 'c'] // With ignore const [first, , ...rest] = arr; rest; // ['c'] ``` 还可收集函数参数为数组。 ```javascript function directions(first, ...rest) { console.log(rest); } directions('a', 'b', 'c'); // ['b', 'c']; ``` 代替 apply。 ```javascript function foo(x, y, z) {} const args = [1,2,3]; // 下面两句效果相同 foo.apply(null, args); foo(...args); ``` 对于 Object 而言,用于组合成新的 Object 。(ES2017 stage-2 proposal) ```javascript const foo = { a: 1, b: 2, }; const bar = { b: 3, c: 2, }; const d = 4; const ret = { ...foo, ...bar, d }; // { a:1, b:3, c:2, d:4 } ``` 此外,在 JSX 中 Spread Operator 还可用于扩展 props,详见 [Spread Attributes](#spread-attributes)。 ### Promises Promise 用于更优雅地处理异步请求。比如发起异步请求: ```javascript fetch('/api/todos') .then(res => res.json()) .then(data => ({ data })) .catch(err => ({ err })); ``` 定义 Promise 。 ```javascript const delay = (timeout) => { return new Promise(resolve => { setTimeout(resolve, timeout); }); }; delay(1000).then(_ => { console.log('executed'); }); ``` ### Generators dva 的 effects 是通过 generator 组织的。Generator 返回的是迭代器,通过 `yield` 关键字实现暂停功能。 这是一个典型的 dva effect,通过 `yield` 把异步逻辑通过同步的方式组织起来。 ```javascript app.model({ namespace: 'todos', effects: { *addRemote({ payload: todo }, { put, call }) { yield call(addTodo, todo); yield put({ type: 'add', payload: todo }); }, }, }); ``` ## React Component ### Stateless Functional Components React Component 有 3 种定义方式,分别是 `React.createClass`, `class` 和 `Stateless Functional Component`。推荐尽量使用最后一种,保持简洁和无状态。这是函数,不是 Object,没有 `this` 作用域,是 pure function。 比如定义 App Component 。 ```javascript function App(props) { function handleClick() { props.dispatch({ type: 'app/create' }); } return
${props.name}
} ``` 等同于: ```javascript class App extends React.Component { handleClick() { this.props.dispatch({ type: 'app/create' }); } render() { return
${this.props.name}
} } ``` ### JSX #### Component 嵌套 类似 HTML,JSX 里可以给组件添加子组件。 ```html