这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
Flux 思想
数据的单项流动,仰赖MVVM模式
action creator
创造熊猫的,叫做panda creator
创造小狗的,叫做dog creator
比如下面的箭头函数就是一个action creator:
() => ({“type” : “ADD”})
总结:action creator是个函数,返回Action
connect装饰器中使用action creator
export default connect(
({counterReducer}) => ({
v : counterReducer.v
}),
{
add(){
return {"type" : "ADD"}
},
minus(){
return {"type" : "MINUS"}
}
}
)(App)
add()和minus()的键 都是Action creator,罗列一个个返回Action的函数。
创建counterAction.js 文件
向外暴露两个action creator:
export const add = () => ({"type" : "ADD"});
export const minus = () => ({"type" : "MINUS"});
组件只需要引入 counterAction.js文件,并修改connect函数
export default connect(
({counterReducer}) => ({
v : counterReducer.v
}),
{
add,
minus
}
)(App)
bindActionCreators 绑定action creator
调用 需要使用 命名空间
import React from 'react';
import { connect } from "react-redux";
import * as counterActions from "./actions/counterActions";
import {bindActionCreators} from "redux";
class App extends React.Component{
constructor(){
super();
}
render(){
return(
<div>
<h1>{this.props.v}</h1>
<button onClick={()=>{
this.props.counterActions.add();
}}>按我+</button>
<button onClick={() => {
this.props.counterActions.minus();
}}>按我-</button>
</div>
)
}
}
export default connect(
({counterReducer}) => ({
v : counterReducer.v
}),
(dispatch) => ({
counterActions: bindActionCreators(counterActions , dispatch)
})
)(App)
异步
redux-thunk
thunk是形式转换程序的意思
安装依赖
npm install --save redux-thunk
安装thunk之后,action文件中就可以写 两个括号了,如下
export const addAfter2000ms = () => () => {}
export const addAfter2000ms = () => (dispatch) => {}
第二个括号中系统附送 dispatch
| 总结 |
|---|
| 1)thunk是一个语法转换程序,装了之后,可以在action文件中写() => () => {}形式 |
| 2)异步真正在action文件中执行 |
| 3)保持了组件文件的美观、整齐 |
| 4)reducer中不额外增加if分支。 |
async 和 redux-thunk结合使用
import axios from 'axios';
const GETDATA = "GETDATA"
const getData = (url:any, value:any) => async (dispatch:any) => {
let results = await axios.post(url, value, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res => res.data.data)
.catch(error => {
console.log(error);
});
dispatch(fetchData(results));
}
const fetchData = (results:any) => ({type: GETDATA, results})
export {
getData
}
redux-saga
saga是英语“传奇”的意思。它的思想是“拦截”。
redux-saga的大体过程如下:
安装依赖
npm install --save redux-saga
需要我们补充babel的插件。babel要想处理加星函数、Promise等,必须要装babel-plugin-transform-runtime。
npm install --save-dev babel-plugin-transform-runtime
修改webpack.config.js: 找到这一行: 添加一个插件 transform-runtime
plugins: ['transform-object-rest-spread','transform-runtime']
创建saga.js
export const helloSaga = function* () {
console.log('我是saga,你好!')
}
函数有一个星,叫做产生器
修改main.js 入口文件 参考手册 redux-saga.js.org/docs/introd…
| 总结: |
|---|
| 1)组件、action、reducer文件都保持了形式上的美感,没有破坏代码整齐性。没有两个()的action,保持了高度的整齐性; |
| 2)真正实现异步在saga文件中,而thunk是action文件。 |
| 3)saga的思路是拦截。thunk的思路是“形式转换”,让异步的action写两个圆括号。因为saga的思路好,所以它“易于插拔”,感觉“在外部”管理整个业务逻辑,是一个独立的部分。 |
| 4)saga结束之后,最终的产物是一次put,表示转发action。 |
Promise
同步函数的特点
- 函数必须所有语句执行完毕,再执行后面的语句
- 函数体内用return返回值
- 函数调用时,等号左侧用变量接收
异步函数的特点:
- 异步函数会先之后后面的语句,等后面语句清空(同步栈执行完毕)、异步也做完了,执行回调函数;
- 函数体内没有return这个词语,必须用回调函数来返回值;
- 函数调用的时候,不能写等号,不能用变量来接收值,必须用回调函数来接手值。
写一个异步函数,2000ms返回一个随机数
function getNumberAfter2000ms(cb){
setTimeout(function(){
cb(Math.random());
},2000);
}
getNumberAfter2000ms(function(a){
console.log(a);
});
console.log("你好");
回调黑洞(callback hell)
调用3次getNumberAfter2000ms 用6s得到3个数
getNumberAfter2000ms(function(a){
console.log(a);
getNumberAfter2000ms(function (b) {
console.log(b);
getNumberAfter2000ms(function (c) {
console.log(c);
});
});
});
认识Promise
- Promise 是ES6中提供的一个语法糖,可以简化异步函数的书写。
- 是ES6提供的内置构造函数
封装一个Promise
写一个异步函数,函数返回Promise实例,而Promise实例圆心上有then方法
整体结构
function getNumberAfter2000ms(){
return new Promise();
}
getNumberAfter2000ms().then();
实例化Promise的时候,必须传入一个函数 (resolve,reject)=>{}。形参resolve表示成功,reject表示失败。 resolve就是成功时候回调,由then里面传入。
function getNumberAfter2000ms(){
return new Promise((resolve , reject) => {
setTimeout(function(){
resolve(Math.random());
},2000);
});
}
getNumberAfter2000ms().then(function(a){
console.log(a);
});
此时就可以链式调用一个异步函数,就不需要使用 毁掉黑洞了。
getNumberAfter2000ms()
.then(function(a){
console.log(a);
return getNumberAfter2000ms();
})
.then(function (a) {
console.log(a);
return getNumberAfter2000ms();
})
.then(function (a) {
console.log(a);
return getNumberAfter2000ms();
});
自己封装一个 promise 函数
class ChengNuo{
constructor(fn){
this.fn = fn;
}
then(cb){
this.fn(cb)
}
}
function getAfter2s(){
return new ChengNuo((resolve,reject) => {
setTimeout(function(){
resolve(Math.random())
},1000)
})
}
getAfter2s().then(function(b){
console.log(b);
return getAfter2s()
})
fetch()函数 --兼容性差
表示 “请求、得到”的意思。天生返回 Promose的实例
原生fetch 用的不是XMLHttpRequest对象,即 fetch不是ajax。
axios
功能: 使用XMLHttpRequest对象,模拟了Promise的语法,和fetch语法一样。 安装依赖:
npm install --save axios
使用方法:
import axios from "axios";
function* addServer() {
const {m} = yield axios.get("/api/shu").then(data=>data.data);
yield put({ "type": "ADD" , m});
}
async / await
ES7中提供了async/await,可以写同步函数的写法调用异步函数。
async 只能加在function关键字的前面,不能加在箭头函数之前。
function getNumberAfter2000ms(){
return new Promise((resolve , reject) => {
setTimeout(function(){
resolve(Math.random());
},2000);
});
}
async function main(){
const a = await getNumberAfter2000ms().then(data => data);
console.log(a);
const b = await getNumberAfter2000ms().then(data => data);
console.log(b);
const c = await getNumberAfter2000ms().then(data => data);
console.log(c);
}
main();
async的函数里面,可以用await标注语句。await后面必须跟着一个返回Promise实例的函数then方法的执行,then的函数返回值,将被自动被await左边的变量接收(这是c++浏览器底层封装)
await表示等待,它将等待这个异步函数执行完毕。
Generator 加星函数
ES8推出的,非常新,Generator叫做产生器,库打断点的函数,可以有多个返回值的函数。
例子
function* gen(){
console.log("哈哈");
yield "A";
console.log("嘻嘻");
yield "B";
console.log("么么哒");
yield "C";
}
var I = gen(); //激活这个加星函数
I.next() //输出哈哈
I.next() //输出嘻嘻
I.next() //输出么么哒
yield表示“产出”,就是函数的断点。
gen()函数能够让虚拟“游标”就位,在 function* 下一行就位。此时i就可以调用next()方法,表示执行函数到最近的yield。
yield后面的值,也可以被看见
console.log(g.next().value); //输出A
加星函数和Promise搭配堪称完美。
function getNumberAfter2000ms(){
return new Promise((resolve) => {
setTimeout(function(){
resolve(Math.random())
},2000);
});
}
function* gen(){
yield getNumberAfter2000ms();
yield getNumberAfter2000ms();
yield getNumberAfter2000ms();
}
var i = gen(); //激活,准备游标
i.next().value
.then(data=>{
console.log(data);
return i.next().value;
})
.then(data => {
console.log(data);
return i.next().value;
})
.then(data => {
console.log(data);
})
封装一个delay函数
function delay(time){
return new Promise((resolve)=>{
setTimeout(function(){
resolve()
},time)
})
}
function* gen(){
yield delay(2000)
yield Math.random()
}
感谢
谢谢各位在百忙之中点开这篇文章,希望对你们能有所帮助,如有问题欢迎各位大佬指正。
如果觉得写得还行的话,那就点个赞吧。