React 源码中的依赖注入方法


Posted in Javascript onNovember 07, 2018

一、前言

依赖注入(Dependency Injection)这个概念的兴起已经有很长时间了,把这个概念融入到框架中达到出神入化境地的,非Spring莫属。然而在前端领域,似乎很少会提到这个概念,难道前端的代码就不需要解耦吗?前端的代码就没有依赖了?本文将以 React 的源码为例子,看看它是如何使用依赖注入这一设计模式的。

二、依赖注入的基本概念

在看代码之前,有必要先简单介绍一下依赖注入的基本概念。依赖注入和控制反转(Inversion of Control),这两个词经常一起出现。一句话表述他们之间的关系:依赖注入是控制反转的一种实现方式。另一种方式叫依赖查找(Dependency Lookup)。

在控制不反转的情况下,某个类如果依赖另一个类,它会自己来创建依赖:

class Person {
  eat() {
    const dinner = new Dinner('法国菜');
    console.log('开饭啦!,今晚自己做:', dinner.name);
  }
}

class Dinner {
  constructor(name) {
    this.name = name;
  }
}

假设一个人要吃饭,如果控制不反转,就需要自己来做,像上面的代码一样要自己new Dinner。

如果使用控制反转,吃什么就不用自己费脑子了,别人给我做好放到我面前,我直接吃就好!

class Person {
  eat(dinner) {
    console.log('开饭啦!,今晚有大厨给我做:', dinner.name);
  }
}

也就是说,不需要自己来创建依赖的对象了,由外部传入,这就是依赖注入!

三、React 中的依赖注入

众所周知,React 除了可以在浏览器运行外(ReactDOM),也可以制作 App 在手机端运行(ReactNative)。而两者有大量的代码都是可以共享的,这就是依赖注入的使用场景了。

我们来看下具体是如何注入的:

// ReactDOM.js
var ReactDefaultInjection = require('ReactDefaultInjection');
ReactDefaultInjection.inject();

// ReactNative.js
var ReactNativeDefaultInjection = require('ReactNativeDefaultInjection');
ReactNativeDefaultInjection.inject();

注入的位置都在框架代码最开始加载的位置。下面以 ReactDOM 为例子,详细讲解注入的逻辑。

先来看看需要注入的对象都有哪些,定义在 ReactInjection.js 这个文件当中:

var DOMProperty = require('DOMProperty');
var EventPluginHub = require('EventPluginHub');
var EventPluginUtils = require('EventPluginUtils');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactHostComponent = require('ReactHostComponent');
var ReactUpdates = require('ReactUpdates');

var ReactInjection = {
 Component: ReactComponentEnvironment.injection,
 DOMProperty: DOMProperty.injection,
 EmptyComponent: ReactEmptyComponent.injection,
 EventPluginHub: EventPluginHub.injection,
 EventPluginUtils: EventPluginUtils.injection,
 EventEmitter: ReactBrowserEventEmitter.injection,
 HostComponent: ReactHostComponent.injection,
 Updates: ReactUpdates.injection,
};

module.exports = ReactInjection;

这里面每一个 injection 都是一个对象,对象内定义了一个或多个 inject 的方法来注入对应的内容。以ReactUpdates.injection为例子:

// ReactUpdates.js
var ReactUpdatesInjection = {
  injectReconcileTransaction: function (ReconcileTransaction) {
    ...
    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
  },

  injectBatchingStrategy: function (_batchingStrategy) {
    ...
    batchingStrategy = _batchingStrategy;
  },
};

var ReactUpdates = {
  ...
  injection: ReactUpdatesInjection,
};

可以看到 ReactUpdates 依赖的ReactReconcileTransaction和batchingStrategy就是通过这 2 个方法注入进去的。

有了上面的内容,相当于定义好需要依赖的内容了。下一步就是创建具体的依赖内容,然后注入到需要的地方:

// ReactDefaultInjection.js
var ReactInjection = require('ReactInjection');
var ReactReconcileTransaction = require('ReactReconcileTransaction');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');

...

function inject() {
  ...

  ReactInjection.Updates.injectReconcileTransaction(
    ReactReconcileTransaction
  );
  ReactInjection.Updates.injectBatchingStrategy(
    ReactDefaultBatchingStrategy
  );
}

这里的 ReactInjection.Updates 等于 ReactUpdates.injection 这个对象。而 inject 方法,就是在前文的 ReactDOM.js 中调用的方法ReactDefaultInjection.inject()。

上述各个文件整体的调用关系如下:

React 源码中的依赖注入方法

四、总结

本文介绍了依赖注入的基本概念,并结合 React 的源码讲解具体的使用场景。这样做的主要目的是解耦,可以根据实际的上下文传入不同的依赖对象,优雅的实现了代码的抽象与复用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
响应鼠标变换表格背景或者颜色的代码
Mar 30 Javascript
jquery实现心算练习代码
Dec 06 Javascript
深入领悟JavaScript中的面向对象
Nov 18 Javascript
JavaScript实现时间倒计时跳转(推荐)
Jun 28 Javascript
Bootstrap实现导航栏的2种方式
Nov 28 Javascript
三种方式实现瀑布流布局
Feb 10 Javascript
JavaScript实现简单的双色球(实例讲解)
Jul 31 Javascript
[js高手之路]单例模式实现模态框的示例
Sep 01 Javascript
js实现图片粘贴上传到服务器并展示的实例
Nov 08 Javascript
JavaScript实现的贝塞尔曲线算法简单示例
Jan 30 Javascript
详解easyui 切换主题皮肤
Apr 04 Javascript
Vue.js实现tab切换效果
Jul 24 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
Nov 07 #Javascript
详解react native页面间传递数据的几种方式
Nov 07 #Javascript
微信小程序使用npm支持踩坑
Nov 07 #Javascript
Angular Material Icon使用详解
Nov 07 #Javascript
详解Webpack loader 之 file-loader
Nov 07 #Javascript
JS复杂判断的更优雅写法代码详解
Nov 07 #Javascript
javascript动态创建对象的属性详解
Nov 07 #Javascript
You might like
一个简单的PHP入门源程序
2006/10/09 PHP
php入门之连接mysql数据库的一个类
2012/04/21 PHP
PHP gbk环境下json_dencode传送来的汉字
2012/11/13 PHP
PHP设计模式之调解者模式的深入解析
2013/06/13 PHP
ThinkPHP的L方法使用简介
2014/06/18 PHP
PHP的PDO事务与自动提交
2019/01/24 PHP
Javascript 赋值机制详解
2014/11/23 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
2015/04/15 Javascript
基于jquery实现智能提示控件intellSeach.js
2016/03/17 Javascript
jQuery的文档处理程序详解
2016/05/10 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
2016/08/20 Javascript
JavaScript中this的用法实例分析
2016/12/19 Javascript
很棒的一组js图片轮播特效
2017/01/12 Javascript
PHP7新特性简述
2017/06/11 Javascript
vue实现nav导航栏的方法
2017/12/13 Javascript
video.js 实现视频只能后退不能快进的思路详解
2018/08/09 Javascript
浅谈Fetch 数据交互方式
2018/12/20 Javascript
Vue实现微信支付功能遇到的坑
2019/06/05 Javascript
vue中进行微博分享的实例讲解
2019/10/14 Javascript
Vue实现点击当前行变色
2020/12/14 Vue.js
[02:17]2016国际邀请赛中国区预选赛VG战队领队采访
2016/06/26 DOTA
[01:00] DOTA2英雄背景故事第五期之重力引力法则谜团
2020/07/16 DOTA
Python进程通信之匿名管道实例讲解
2015/04/11 Python
python 第三方库的安装及pip的使用详解
2017/05/11 Python
Python实现FTP弱口令扫描器的方法示例
2019/01/31 Python
Python3批量移动指定文件到指定文件夹方法示例
2019/09/02 Python
Chupi官网:在爱尔兰手工制作的订婚、结婚戒指和精美珠宝
2020/09/28 全球购物
database面试题
2013/03/28 面试题
我的网上商城创业计划书
2013/12/26 职场文书
大学生职业生涯规划书模板
2014/01/03 职场文书
教师年度考核评语
2014/04/28 职场文书
职位说明书范文
2014/05/07 职场文书
迎新晚会策划方案
2014/06/13 职场文书
求职简历自荐信
2014/06/18 职场文书
数学备课组工作总结
2015/08/12 职场文书
SQL Server 数据库实验课第五周——常用查询条件
2021/04/05 SQL Server