Preface
从参加工作到此刻动笔已经有7个周了,前三个周在沈阳主要使用vue+element-ui做一个前端的后台管理系统页面。后一个月被派到长春,目前所在的项目组主要使用React+dva+antd(ui)做一个中台系统的前端和中台管理界面。这7周的工作是我对编程有了一定的了解。虽说是面的JAVA开发工程师进的公司,但进组的第一天就被商量改做前端。从什么页不会,到慢慢的开始完成需求任务,感觉还是不错。但仍感到自身底子太薄,需要不断的加强。
特此,根据DVA官网上的源码解析教程,做了一系列学习笔记,这是第一篇【初始篇】
package.json里的秘密
当我们从GitHub上git clone一个dva项目后,只需要npm install
然后npm start
就可以启动了,但我们使用完npm start
命令时,到底发生了什么?在作者的文档中,我们找到了答案“去package.json中寻找”。
package.json是一个项目的配置文件,在这里可以找到项目的所有依赖。
package.json中的devDependencies可以找到的依赖,在npm中一样可以找的到。
在了解完roadhog
的作用后,我们便从入口文件src/index.js
下手:
在src/index.js
中,dva一共做了如下几件事:
- 0.从‘dva’依赖中引入dva:
import dva from 'dva'
; - 1.通过函数生成一个app对象:
const app = dva()
; - 2.加载插件:
app.use({})
; - 3.注入model:
app.model(require(;./models/example'))
; - 4.添加路由:
app.router(require('./routes/indexAnother'))
; - 5.启动:
app.start('#root')
;
这六步中,dva完成了使用React解决view层
、redux管理model
、saga解决异步
的主要功能。目前前端工程师都在做分离‘动态的data’和‘静态的view’。MVX思想并没有改变。
dva
dva源码
遵循上面的方法,先查看package.json
,引用依赖很好的说明了dva的功能:统一view层。
//dva使用的依赖如下:
"babel-runtime": "^6.26.0", // 一个编译后文件引用的公共库,可以有效减少编译后的文件体积
"dva-core": "^1.1.0", // dva 另一个核心,用于处理数据层
"global": "^4.3.2", // 用于提供全局函数的引用
"history": "^4.6.3", // browserHistory 或者 hashHistory
"invariant": "^2.2.2", // 一个有趣的断言库
"isomorphic-fetch": "^2.2.1", // 方便请求异步的函数,dva 中的 fetch 来源
"react-async-component": "^1.0.0-beta.3", // 组件懒加载
"react-redux": "^5.0.5", // 提供了一个高阶组件,方便在各处调用 store
"react-router-dom": "^4.1.2", // router4,终于可以像写组件一样写 router 了
"react-router-redux": "5.0.0-alpha.6",// redux 的中间件,在 provider 里可以嵌套 router
"redux": "^3.7.2" // 提供了 store、dispatch、reducer
src/index.js
你可以在这里找到index.js
在这里,dva做了三件重要的事情:
- 1.使用call给dva-core实例化app(此时还只有数据层)的start方法增加一些新功能「通过代理模式给model层增加了view层」。
- 2.使用react-redux完成了react到redux的连接
- 3.添加redux的中间件react-redux-router,强化了history对象的功能。
使用call方法实现代理模式
dva中实现代理模式的方法如下:
- 1.新建function,函数内实例化一个app对象。
- 2.新建变量指向该对象希望代理的方法,
oldStart = app.start
。 - 3.新建同名方法start,在其中使用call,指定oldStart的调用者为app。
- 4.令
app.start = start
,完成对app对象的start方法的代理。
export default function(opts = {}){
// ...初始化 route ,和添加 route 中间件的方法。
/**
* 1.新建 function ,函数内实例化一个app对象
*/
const app = core.create(opts, createOpts);
/**
* 2. 新建变量指向该对象希望代理的方法
*/
const oldAppStart = app.start;
app.router = router;
/**
* 4. 令 app.start = start,完成对 app 对象的 start 方法的代理。
* @type {[type]}
*/
app.start = start;
return app;
// router 赋值
/**
* 3.1 新建同名方法 start,
*
*/
function start(container) {
// 合法性检测代码
/**
* 3.2 在其中使用 call,指定 oldStart 的调用者为 app。
*/
oldAppStart.call(app);
// 因为有 3.2 的执行才有现在的 store
const store = app._store;
// 使用高阶组件创建视图
}
}
接 ▶️ 《深度理解DVA源码》(第二篇)