dva.js 知识导图

JavaScript 语言
变量声明
const 和 let
模板字符串
默认参数
箭头函数
模块的 Import 和 Export
ES6 对象和数组
析构赋值
对象字面量改进
Spread Operator
Promises
Generators
React Component
Stateless Functional Components
JSX
Component 嵌套
className
JavaScript 表达式
Mapping Arrays to JSX
注释
Spread Attributes
Props
propTypes
往下传数据
往上传数据
CSS Modules
理解 CSS Modules
定义全局 CSS
classnames Package
Reducer
增删改
嵌套数据的增删改
Effect
Effects
put
call
select
错误处理
全局错误处理
本地错误处理
异步请求
GET 和 POST
统一错误处理
Subscription
异步数据初始化
path-to-regexp Package
Router
Config with JSX Element (router.js)
Route Components
通过 connect 绑定数据
Injected Props (e.g. location)
基于 action 进行页面跳转
dva 配置
Redux Middleware
history
切换 history 为 browserHistory
去除 hashHistory 下的 _k 查询参数
工具
通过 dva-cli 创建项目

JavaScript 语言

变量声明
const 和 let
不要用 var,而是用 const 和 let,分别表示常量和变量。不同于 var 的函数作用域,const 和 let 都是块级作用域。

const DELAY = 1000;let count = 0;
count = count + 1;

模板字符串
模板字符串提供了另一种做字符串组合的方法。

const user = 'world';
console.log(`hello ${user}`);  // hello world// 多行
const content = `Hello ${firstName},Thanks for ordering ${qty} tickets to ${event}.
`;
默认参数
function logActivity(activity = 'skiing') {console.log(activity);
}logActivity();  // skiing

箭头函数
函数的快捷写法,不需要通过 function 关键字创建函数,并且还可以省略 return 关键字。

同时,箭头函数还会继承当前上下文的 this 关键字。

比如:

[1, 2, 3].map(x => x + 1);  // [2, 3, 4]
等同于:[1, 2, 3].map((function(x) {return x + 1;
}).bind(this));

模块的 Import 和 Export
import 用于引入模块,export 用于导出模块。

比如:

// 引入全部
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 里取部分数据存为变量。

// 对象
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

我们也可以析构传入的函数参数。

const add = (state, { payload }) => {return state.concat(payload);
};

析构时还可以配 alias,让代码更具有语义。

const add = (state, { payload: todo }) => {return state.concat(todo);
};

对象字面量改进
这是析构的反向操作,用于重新组织一个 Object 。

const name = 'duoduo';
const age = 8;const user = { name, age }; // { name: 'duoduo', age: 8 }

定义对象方法时,还可以省去 function 关键字。

app.model({reducers: {add() {}  // 等同于 add: function() {}},effects: {*addRemote() {}  // 等同于 addRemote: function*() {}},
});
Spread Operator
Spread Operator 即 3 个点 ...,有几种不同的使用方法。

可用于组装数组。

const todos = ['Learn dva'];
[...todos, 'Learn antd']; // ['Learn dva', 'Learn antd']

也可用于获取数组的部分项。

const arr = ['a', 'b', 'c'];
const [first, ...rest] = arr;
rest;  // ['b', 'c']// With ignore
const [first, , ...rest] = arr;
rest;  // ['c']

还可收集函数参数为数组。

function directions(first, ...rest) {console.log(rest);
}
directions('a', 'b', 'c');  // ['b', 'c'];

代替 apply。

function foo(x, y, z) {}
const args = [1,2,3];
// 下面两句效果相同
foo.apply(null, args);
foo(...args);

对于 Object 而言,用于组合成新的 Object 。

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。

Promises
Promise 用于更优雅地处理异步请求。比如发起异步请求:

fetch('/api/todos').then(res => res.json()).then(data => ({ data })).catch(err => ({ err }));
定义 Promise 。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 把异步逻辑通过同步的方式组织起来。

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 。

function App(props) {function handleClick() {props.dispatch({ type: 'app/create' });}return <div onClick={handleClick}>${props.name}</div>
}

等同于:

class App extends React.Component {handleClick() {this.props.dispatch({ type: 'app/create' });}render() {return <div onClick={this.handleClick.bind(this)}>${this.props.name}</div>}
}

JSX
Component 嵌套
类似 HTML,JSX 里可以给组件添加子组件。

<App><Header /><MainContent /><Footer />
</App>

className
class 是保留词,所以添加样式时,需用 className 代替 class 。

<h1 className="fancy">Hello dva</h1>

JavaScript 表达式
JavaScript 表达式需要用 {} 括起来,会执行并返回结果。

比如:

<h1>{ this.props.title }</h1>
Mapping Arrays to JSX

可以把数组映射为 JSX 元素列表。

<ul>{ this.props.todos.map((todo, i) => <li key={i}>{todo}</li>) }
</ul>

注释

尽量别用 // 做单行注释。

<h1>{/* multiline comment */}{/*multilinecomment*/}{// single line}Hello
</h1>

Spread Attributes
这是 JSX 从 ECMAScript6 借鉴过来的很有用的特性,用于扩充组件 props 。

比如:

const attrs = {href: 'http://example.org',target: '_blank',
};
<a {...attrs}>Hello</a>

等同于

const attrs = {href: 'http://example.org',target: '_blank',
};
<a href={attrs.href} target={attrs.target}>Hello</a>

Props
数据处理在 React 中是非常重要的概念之一,分别可以通过 props, state 和 context 来处理数据。而在 dva 应用里,你只需关心 props 。

propTypes
JavaScript 是弱类型语言,所以请尽量声明 propTypes 对 props 进行校验,以减少不必要的问题。

function App(props) {return <div>{props.name}</div>;
}
App.propTypes = {name: React.PropTypes.string.isRequired,
};

内置的 prop type 有:

PropTypes.array
PropTypes.bool
PropTypes.func
PropTypes.number
PropTypes.object
PropTypes.string

往下传数据

往上传数据

CSS Modules

理解 CSS Modules
一张图理解 CSS Modules 的工作原理:

button class 在构建之后会被重命名为 ProductList_button_1FU0u 。button 是 local name,而 ProductList_button_1FU0u 是 global name 。你可以用简短的描述性名字,而不需要关心命名冲突问题。

然后你要做的全部事情就是在 css/less 文件里写 .button {…},并在组件里通过 styles.button 来引用他。

定义全局 CSS
CSS Modules 默认是局部作用域的,想要声明一个全局规则,可用 :global 语法。

比如:

.title {color: red;
}
:global(.title) {color: green;
}

然后在引用的时候:

<App className={styles.title} /> // red
<App className="title" />        // green

classnames Package
在一些复杂的场景中,一个元素可能对应多个 className,而每个 className 又基于一些条件来决定是否出现。这时,classnames 这个库就非常有用。

import classnames from 'classnames';
const App = (props) => {const cls = classnames({btn: true,btnLarge: props.type === 'submit',btnSmall: props.type === 'edit',});return <div className={ cls } />;
}

这样,传入不同的 type 给 App 组件,就会返回不同的 className 组合:

<App type="submit" /> // btn btnLarge
<App type="edit" />   // btn btnSmall

Reducer
reducer 是一个函数,接受 state 和 action,返回老的或新的 state 。即:(state, action) => state
增删改
以 todos 为例。

app.model({namespace: 'todos',state: [],reducers: {add(state, { payload: todo }) {return state.concat(todo);},remove(state, { payload: id }) {return state.filter(todo => todo.id !== id);},update(state, { payload: updatedTodo }) {return state.map(todo => {if (todo.id === updatedTodo.id) {return { ...todo, ...updatedTodo };} else {return todo;}});},},
};

嵌套数据的增删改
建议最多一层嵌套,以保持 state 的扁平化,深层嵌套会让 reducer 很难写和难以维护。

app.model({namespace: 'app',state: {todos: [],loading: false,},reducers: {add(state, { payload: todo }) {const todos = state.todos.concat(todo);return { ...state, todos };},},
});

下面是深层嵌套的例子,应尽量避免。

app.model({namespace: 'app',state: {a: {b: {todos: [],loading: false,},},},reducers: {add(state, { payload: todo }) {const todos = state.a.b.todos.concat(todo);const b = { ...state.a.b, todos };const a = { ...state.a, b };return { ...state, a };},},
});

Effect
示例:

app.model({namespace: 'todos',effects: {*addRemote({ payload: todo }, { put, call }) {yield call(addTodo, todo);yield put({ type: 'add', payload: todo });},},
});

Effects
put
用于触发 action 。

yield put({ type: 'todos/add', payload: 'Learn Dva' });

call
用于调用异步逻辑,支持 promise 。

const result = yield call(fetch, '/todos');

select
用于从 state 里获取数据。

const todos = yield select(state => state.todos);

错误处理
全局错误处理

dva 里,effects 和 subscriptions 的抛错全部会走 onError hook,所以可以在 onError 里统一处理错误。

const app = dva({onError(e, dispatch) {console.log(e.message);},
});

然后 effects 里的抛错和 reject 的 promise 就都会被捕获到了。

本地错误处理
如果需要对某些 effects 的错误进行特殊处理,需要在 effect 内部加 try catch 。

app.model({effects: {*addRemote() {try {// Your Code Here} catch(e) {console.log(e.message);}},},
});

异步请求

GET 和 POST

import request from '../util/request';// GET
request('/api/todos');// POST
request('/api/todos', {method: 'POST',body: JSON.stringify({ a: 1 }),
});

统一错误处理
假如约定后台返回以下格式时,做统一的错误处理。

{status: 'error',message: '',
}

编辑 utils/request.js,加入以下中间件:

function parseErrorMessage({ data }) {const { status, message } = data;if (status === 'error') {throw new Error(message);}return { data };
}

然后,这类错误就会走到 onError hook 里。

Subscription
subscriptions 是订阅,用于订阅一个数据源,然后根据需要 dispatch 相应的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。格式为

({ dispatch, history }) => unsubscribe 。

异步数据初始化
比如:当用户进入 /users 页面时,触发 action users/fetch 加载用户数据。


app.model({subscriptions: {setup({ dispatch, history }) {history.listen(({ pathname }) => {if (pathname === '/users') {dispatch({type: 'users/fetch',});}});},},
});

path-to-regexp Package
如果 url 规则比较复杂,比如 /users/:userId/search,那么匹配和 userId 的获取都会比较麻烦。这是推荐用 path-to-regexp 简化这部分逻辑。

import pathToRegexp from 'path-to-regexp';// in subscription
const match = pathToRegexp('/users/:userId/search').exec(pathname);
if (match) {const userId = match[1];// dispatch action with userId
}

Router
Config with JSX Element (router.js)

<Route path="/" component={App}><Route path="accounts" component={Accounts}/><Route path="statements" component={Statements}/>
</Route>

详见:react-router

Route Components
Route Components 是指 ./src/routes/ 目录下的文件,他们是 ./src/router.js 里匹配的 Component。

通过 connect 绑定数据
比如:

import { connect } from 'dva';
function App() {}function mapStateToProps(state, ownProps) {return {users: state.users,};
}
export default connect(mapStateToProps)(App);

然后在 App 里就有了 dispatch 和 users 两个属性。

Injected Props (e.g. location)

Route Component 会有额外的 props 用以获取路由信息。

location
params
children

基于 action 进行页面跳转

import { routerRedux } from 'dva/router';// Inside Effects
yield put(routerRedux.push('/logout'));// Outside Effects
dispatch(routerRedux.push('/logout'));// With query
routerRedux.push({pathname: '/logout',query: {page: 2,},
});

除 push(location) 外还有更多方法,详见 react-router-redux

dva 配置

Redux Middleware
比如要添加 redux-logger 中间件:

import createLogger from 'redux-logger';
const app = dva({onAction: createLogger(),
});

注:onAction 支持数组,可同时传入多个中间件。

history
切换 history 为 browserHistory

import { browserHistory } from 'dva/router';
const app = dva({history: browserHistory,
});

去除 hashHistory 下的 _k 查询参数

import { useRouterHistory } from 'dva/router';
import { createHashHistory } from 'history';
const app = dva({history: useRouterHistory(createHashHistory)({ queryKey: false }),
});

工具
通过 dva-cli 创建项目
先安装 dva-cli 。

$ npm install dva-cli -g

然后创建项目。

$ dva new myapp

最后,进入目录并启动。

$ cd myapp
$ npm start

每天一句中文式外语

すみません(死咪妈森)对不起
ありがとございます(啊里旮兜狗达一妈死)谢谢
いいえ,どういたしまして(易爷,豆以他西妈西忒)不用谢
おやすみなさい(呕丫死咪那塞)晚安
はい(害易)是的
いいえ(易爷)不是的
いただきます(以它搭ki妈寺)我吃啦
ごちそうさまでした(狗期搜物撒妈得西它)我吃好了
はは(哈哈)妈妈
ちち(欺欺)爸爸
そふ(搜咐)祖父/外祖父
そば(搜吧)祖母/外祖母
りょうしん(料心)父母
むすこ(姆思抠)儿子
むすめ(姆思没)女儿
あに(啊妮)哥哥
あね(啊内)姐姐
おとうと(哦偷务透)弟弟
いもうと(以摸乌透)妹妹
おじ(哦激)伯伯/叔叔/舅舅/姑父

dva.js 知识导图相关推荐

  1. CV:人工智能之计算机视觉方向的简介(CV发展史+常用数据集+CV职位)、传统方法对比CNN类算法、计算机视觉十大应用(知识导图+经典案例)之详细攻略

    CV:人工智能之计算机视觉方向的简介(CV发展史+常用数据集+CV职位).传统方法对比CNN类算法.计算机视觉十大应用(知识导图+经典案例)之详细攻略 目录 计算机视觉的简介 1.计算机视觉的研究方向 ...

  2. 0元包邮 | 多传感器融合感知知识导图

    "传感器融合技术"是自动驾驶的核心技术.传感器是汽车感知周围的环境的硬件基础,在实现自动驾驶的各个阶段都必不可少. 随着自动驾驶无人驾驶技术的应用落地,越来越多的伙伴们加入到研究学 ...

  3. Android知识导图

    Android知识导图

  4. 考研线性代数知识导图

    自制考研线性代数知识导图,知识点源于李永乐线代讲义+张宇线代9讲及视频课程笔记,含真题重点知识点标注和补充. 经验: 零基础时看了张宇课程(基础+强化),较有趣味性适合入门,但是需要自己额外做一些习题 ...

  5. 编程随笔-ElasticSearch知识导图(4):搜索

    1. 原理   全文搜索是ES的核心功能.ES中的数据按数据特性可分为两类:确切值及全文文本.ES中如keyword,date这些类型的值都可视为确切值.而text类型的值则视为全文文本数据.   为 ...

  6. 第七章 查找 知识导图

    第七章知识导图:

  7. 【硬核干货】通信行业知识导图合集(源文件)

    大家好,今天给大家发的是鲜枣课堂压箱底的宝贝--通信行业知识导图. 注意!是全部的知识导图哦!而且都是源文件,可以直接进行编辑的. 注意: 1 请勿用于商业用途. 2 mmap文件用mindmanag ...

  8. D3.js — 思维导图

    http://www.lai18.com/content/508828.html 思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩 ...

  9. Linux服务器知识导图,整理分享一些 Linux思维导图(值得收藏)_网站服务器运行维护,Linux...

    Win10 改 Win7,BIOS 怎么设置?_网站服务器运行维护 Win10改Win7,BIOS设置方法:首先进入到BIOS界面:然后将"secure"改为disabled:接着 ...

最新文章

  1. 454. 4Sum II
  2. No.6 建立swap分区、进程、安装软件包的方法(rpm,yum,编译)
  3. 生成式对抗网络Generative Adversarial Networks(GANs)
  4. c语言整数与平均值,编写求一组整数的和与平均值的程序
  5. Python笔记(十五)_异常处理
  6. python字典的内置函数_python – 用于字典转换的特殊方法名称的内置函数
  7. cookie 原理及应用
  8. 截至2018年,目前,企业主流的消息中间件有哪些?各有什么优缺点?面试常问 RabbitMQ使用较多
  9. Onvif开发之代码框架生成篇
  10. Skype For Asterisk 的安装及使用
  11. xlwings 合并单元格 读取_将16家公司财务报表数据过入合并底稿表格,我只用了1分钟...
  12. 5.Django 数据库多表查询
  13. knockoutjs介绍
  14. mac如何使用命令行删除文件
  15. NFT+DeFi =NFTFI
  16. 借微信更新说说有关版本的那些事儿
  17. 机器学习——支持向量机——硬间隔与支持向量
  18. java孙膑与庞涓_鬼谷子数问题的JAVA实现
  19. 无聊科技正经事周刊(第5期):五一长假与虚拟旅行
  20. 通用型与专用型MUC/SOC

热门文章

  1. tmemo 选择消除行_无线耳机新选择
  2. 转发文章最多的朋友可以免费进入价值99元的《湾区AI精英会》海归圈子
  3. 记录博客第一次上热门
  4. 安利产品所谓高品质的真相
  5. 在html表格中怎么创建下拉列表,在html网页中如何做个下拉列表?下拉列表的方法有哪几种?...
  6. 使用carbon_东华大学《Carbon》多孔碳纳米纤维复合膜,优异电磁波吸收性能!
  7. SHTML+INC机制说明!
  8. 因虚假广告,顺丰被罚!
  9. iPhone 14不会全部采用挖孔屏 仅两款Pro版采用
  10. 安卓阵营最强Soc!骁龙898即将亮相:小米12系列本月底前后首发