200行代码写一个简易的dva

在美团实习的时候,第一次接触到dva这样的react框架,回学校的时候,就想有机会自己实现一下这样的框架,虽然自己水平有限,但是可以试一试哈。 目标是实现dva model的同步和异步 dispatch action。

看看 dva 的构成

let counterModel = {namespace: 'counter',state: {num: 0}reducers: {add(state, action){return {num: state.num   1}	}}}

对state的更新

var app = new dva();
app.model(counterModel);
app.start();
app._store.dispatch({type: 'counter/add'
});

上述就是 dva 对 state 的更新, 通过dispatch {type: A / B} 其中 A 是指 model的 namespace, B 是指 model 中 reducers 具体的reducer方法。

其中 dva 对异步的处理是用 redux-saga 处理的,因为作者并不熟悉redux-saga,拿 redux-thunk 代替了。

好,我们开工了

  • 第一步 创建store

      const createStore = (reducer, initialState) => {let currentReducer = reducer;let currentState = initialState;let listener = () => { };return {getState() {return currentState;},dispatch(action) {let {type} = action;currentState = currentReducer(currentState, action);listener();return action;},subscribe(newListener) {listener = newListener;}}} 
    

store 主要是 存储数据,开放state更新接口。

  • 第二步 引入中间件 applyMiddleware

     const compose = (...funcs) => {if (funcs.length === 0) {return arg => arg}if (funcs.length === 1) {return funcs[0]}const last = funcs[funcs.length - 1]const rest = funcs.slice(0, -1)return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args));}const applyMiddleware = (...middlewares) => {return (createStore) => (reducer, initialState, enhancer) => {var store = createStore(reducer, initialState, enhancer)var dispatch = store.dispatch;var chain = [];var middlewareAPI = {getState: store.getState,dispatch: (action) => store.dispatch(action)}chain = middlewares.map(middleware => middleware(middlewareAPI))dispatch = compose(...chain)(store.dispatch)return {...store,dispatch}}}
    

redux 中间件 洋葱模型,修改了dispatch 方法。

  • 引入异步中间件redux-thunk和logger中间件

     	const logger = store => next => action => {console.log('prevState', store.getState());let result = next(action);console.log('nextState', store.getState());return result;};const thunk = ({dispatch,getState}) => next => action => {if (typeof action === 'function') {return action(dispatch, getState);}return next(action);}
    

    这里引入 redux-thunk 做异步处理。

  • 加入测试model

      let counterModel = {namespace: 'counter',state: {num: 0},reducers: {add(state, action) {console.log('reducer add executed');return {num: state.num   1}},asyncAdd(state, action) {console.log('reducer asyncAdd executed');return {num: state.num   1}},test(state, action) {console.log('reducer test executed');return {state}}}};let userModel = {namespace: 'user',state: {name: 'xxxx'},reducers: {modify(state, {payload}) {console.log('reducer modify executed');let {name} = payloadreturn {name}}}};
    
  • 对不同model下的reducer进行分发

      const combineReducer = (reducers) => (state = {}, action) => {let {type} = action;let stateKey = type.split('/')[0];let reducer = type.split('/')[1];reducers.map((current) => {if (current.name === reducer) {state[stateKey] = current(state[stateKey], action);}});return state;}
    

    这里因为 combineReducer 是 reducer的总入口,在这里根据action 的 type 转发到具体model下的reducer方法

  • dva 构造函数

      class dva {constructor() {this._models = [];this._reducers = [];this._states = {};}model(model) {this._models.push(model);}start() {for (var i = 0; i < this._models.length; i  ) {this._states[this._models[i].namespace] = {...this._models[i].state};Object.keys(this._models[i].reducers).map((key) => {if (this._models[i].reducers.hasOwnProperty(key)) {this._reducers.push(this._models[i].reducers[key]);}})}var rootReducer = combineReducer(this._reducers);let createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore);this._store = createStoreWithMiddleware(rootReducer, this._states);this._store.subscribe(() => {console.log(this._store.getState());})}}
    

    dva 构造方法主要工作是缓存model,创建store。

测试数据

var app = new dva();
app.model(counterModel);
app.model(userModel);app.start();
app._store.dispatch({type: 'counter/add'
});app._store.dispatch({type: 'user/modify',payload: {name: 'shadow'}
})app._store.dispatch((dispatch, getState) => {setTimeout(() => {dispatch({type: 'counter/asyncAdd'})}, 5000);
})

控制台的输出

一点留言

这个当然是最粗糙的dva部分实现了,因为本身自己并没有去看dva源码,只是看了dva API 蒙头实现下,其中已经有很多很优秀的redux周边生态,例如redux-thunk,logger等。当然也是复习了一下部分redux源码了,当作自己学习的一个阶段学习吧,最后像dva作者 陈谦 致敬。

最后留个地址吧:

http://oymaq4uai.bkt.clouddn.com/index.js


更多专业前端知识,请上 【猿2048】www.mk2048.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366596.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 切换root_Linux运维服务篇:流量监控工具iftop部署及详细参数分享

Linux流量监控工具--iftop介绍&#xff1a;在类Unix系统中可以使用top查看系统资源、进程、内存占用等信息。查看网络状态可以使用netstat、nmap等工具。若要查看实时的网络流量&#xff0c;监控TCP/IP连接等&#xff0c;则可以使用iftop。一、iftop是什么&#xff1f;iftop是类…

Python特殊函数

exec()&#xff1a;执行动态的字符串代码&#xff0c;和eval类似&#xff0c;不过eval接受表达式。 它可接受&#xff1a;1.代码字符串 2.文件对象 3.代码对象 4.tuple >>> exec(a2) >>> a 2 >>> exec(print(\5\)) 5 eval()&#xff1a;接受一个字…

Java7 –回顾

我开始写博客文章&#xff0c;介绍即将发布的Java8版本中的新增功能 &#xff0c;并认为我将从快速回顾一下Java7带给我们的内容开始。 Java7于2011年7月发布&#xff0c;被描述为“更具进化性而非革命性”。 “有一些重大的改进&#xff0c;但是并没有真正令人惊叹或突破性的…

皖西学院计算机证书,下半年皖西学院计算机等级考试报名时间

根据《皖西学院2017下半年全国计算机等级考试报名通知》得知&#xff0c;2017下半年全国计算机等级考试报名时间7月3日上午09:00分至7月18日17点30分。下面yjbys小编就为大家分享一篇皖西学院计算机等级考试报名具体内容&#xff0c;希望大家认真阅读!一、报名及网上缴费时间&a…

RabbitMQ安装以及集群部署

本次记录安装RabbitMQ的过程&#xff0c;只针对MAC下单机版安装、单机集群安装方法以及配置haproxy负载均衡。 RabbitMQ单机版本安装RabbitMQ单机集群安装方法&#xff08;适合开发练习&#xff09;RabbitMQ配置haproxy负载均衡RabbitMQ集群测试&#xff08;待续&#xff09;参…

前端通过spark-md5.js计算本地文件md5

背景&#xff1a;说到本人第一次使用spark-md5.js还是差不多一年以前的时候了&#xff0c;当时后台老大说要搞一个文件分片上传的功能。我当时就心想&#xff1a;what&#xff1f;啥是文件分片上传&#xff0c;完全没听过好吗&#xff1f;至于我当时内心那个慌就不多描述了&…

r 保留之前曲线_生存曲线居然能够批量绘制了

生信分析第三步&#xff1a;生存曲线批量绘制各位解螺旋的小伙伴大家好&#xff0c;我是先锋宇&#xff0c;欢迎大家来到每周日的先锋宇专栏&#xff0c;经过前两期推文的学习&#xff0c;很多小伙伴都私信我说从先锋宇助教的专栏很接地气&#xff0c;自己能够开始慢慢处理数据…

关于窗口的一些小脚本

一般窗口分为两种情况 &#xff1a; 1、window.open 浏览器样式窗口 ⑴ 属性&#xff1a;window.open(index.html, newpage, height800, width60, top20, left50, toolbarno, menubarno, scrollbarsno, resizableno, locationno, statusno) 参数&#xff1a;window.open 弹出新…

基于vue自动化表单实践

背景 B端系统表单较多&#xff0c;且表单可能含有较多字段字段较多的表单带来了大片HTML代码在大片HTML中&#xff0c;混杂着参数绑定、事件处理等逻辑&#xff0c;不利于维护技术栈 Vue&#xff0c;Element(默认表单布局)适合中后台项目快速开发 目标 通过json配置快速生成表单…

天津科技大学计算机学院复试分数线,2021天津科技大学研究生复试分数线

2021天津科技大学研究生复试分数线已经公布&#xff0c;包含学术学位、专业学位、专项计划复试分数线&#xff0c;供大家参考&#xff0c;如意了在此祝广大考研学子都能顺利上岸。一、2021年天津科技大学研究生分数线1&#xff0e;专业分数线各学院严格执行《2021年全国硕士研究…

使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码

概述&#xff1a; 在本教程中&#xff0c;我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件。 如果您正在处理大型或中型项目&#xff0c;并且开始时有超过5个以上的表&#xff0c;则可能会发现此插件是自动生成映射域对象java文件和相应* .hbm.xml的绝佳工具…

idea本地跑如何看gc日志_线上故障如何快速排查?来看这套技巧大全

简介&#xff1a;有哪些常见的线上故障&#xff1f;如何快速定位问题&#xff1f;本文详细总结工作中的经验&#xff0c;从服务器、Java应用、数据库、Redis、网络和业务六个层面分享线上故障排查的思路和技巧。较长&#xff0c;同学们可收藏后再看。前言线上定位问题时&#x…

【第七次JAVA课,java语法基础】课件总结

没上课&#xff0c;不写总结&#xff01; 空着&#xff0c;会专门写篇总结java的io和nio的随笔。 转载于:https://www.cnblogs.com/limitCM/p/9997971.html

计算机技术与分析化学论文,分析化学(论文).doc

分析化学(论文)分析化学在生活中的应用化学化工学院 胡成摘 要&#xff1a;通过简单介绍有关分析化学在食品安全、药品检测、化妆品研究和环境监测的应用&#xff0c;阐明分析化学在人类生活中的重要作用。关 键 词&#xff1a;分析化学 食品安全 药品检测 化妆品研究 环境监测…

从零打造在线版H5页面生成器

想必你一定使用过易企秀或其它微场景生成工具制作过炫酷的h5页面&#xff0c;除了感叹其神奇之处有没有想过其实现方式呢&#xff1f;从设计者的角度来看待问题&#xff0c;会有不一样的收获&#xff0c;本文将从零开始&#xff0c;使用node技术来设计实现一款精简版的易企秀 G…

使用Struts2,Hibernate和MySQL BLOB开发个人迷你相册应用程序–第1部分

概述&#xff1a; 在本研讨会中&#xff0c;我们将开发一个Web应用程序&#xff0c;可用于创建漂亮的照片库。 您可以将其托管在Web服务器中&#xff0c;也可以在自己的PC中使用以维护和管理照片集。 使用本教程&#xff0c;您将能够了解与Struts2和Hibernate相关的以下重要内容…

Activity并行网关和排他网关

说一说activiti中的排他网关和并行网关 activiti工作流中我们经常用到的网关有两种&#xff1a; 1. Exclusive Gateway 排他网关 排他网关.png 排他网关&#xff08;也叫异或&#xff08;XOR&#xff09;网关&#xff0c;或更技术性的叫法 基于数据的排他网关&#xff09;&…

ValueError: too many values to unpack

Error msg: 执行: python manage,py makemigrations 报错:Value: too many values to unpack 问题: django第一次数据库迁移之后, apps中的model位置改变了, 导致之前生成的迁移文件检测不到原来的位置 解决: 删除所有的迁移文件重新迁移, 或者将之前的迁移文件的路径修改正确 …

安徽省计算机二级考试vfp试题,安徽省计算机二级VFP考试理论模拟试题附答案

《安徽省计算机二级VFP考试理论模拟试题附答案》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《安徽省计算机二级VFP考试理论模拟试题附答案(19页珍藏版)》请在人人文库网上搜索。1、一、单项选择题(每题1分&#xff0c;共40分) 1. 计算机能够自动工作&#xff0c;主…

你不懂js系列学习笔记-异步与性能- 02

第二章&#xff1a;回调 原文&#xff1a;You-Dont-Know-JS 主要理解 “回调地狱&#xff08;callback hell&#xff09;”痛苦的点到底是哪&#xff0c;以及尝试拯救回调。 1. 首先从实际生活中模拟 我相信大多数读者都曾经听某个人说过&#xff08;甚至你自己就曾这么说&…