前端理解依赖注入(控制反转)

前端的技术的极速发展,对前端同窗来讲也是一个不小的挑战,有各类各样的东西须要学,在开发过程当中常常会被后端同窗嘲讽,对于前端来说根本就不存在类的概念,不少时候须要把大量的业务代码堆积在页面或者组件中,使组件和页面变得特别的臃肿,一旦业务逻辑复杂的状况下,及时组件化作的很好,仍然避免不了难以维护。前端

之因此会被后端同窗嘲讽,一基础掌握不扎实,对前端理解不到位,二缺少面向对象思想,三对业务与基础傻傻分不清楚。ECMAScript 2015Type Script的推出,提出了一个很重要的概念就是class(类)的概念。在没有class以前为了前端可以有类的概念,一直都是使用构造函数模拟类的概念,经过原型完成继承。vue

虽然前端提出了不少概念(模块化,组件化...),我的以为面向对象的应用是前端对于项目以及总体架构来说是一件利器,代码结构好与坏与面向对象有必定的关系,但不是所有。不过咱们能够借助计算机领域的一些优秀的编程理念来必定程度上解决这些问题,接下来简单的说下依赖注入(控制反转)。java

什么是依赖注入

依赖注入通常指控制反转,是面向对象编程中的一种设计原则,能够用来减低计算机代码之间的耦合度。其中最多见的方式叫作依赖注入,还有一种方式叫依赖查找。经过控制反转,对象在被建立的时候,由一个调控系统内全部对象的外界实体将其所依赖的对象的引用传递给它。也能够说,依赖被注入到对象中。编程

从上面的描述中能够发现,依赖注入发生在2个或两个以上类,好比如今有两个类AB类,若是A是基础类存在的话,B作为业务类存在,B则会依赖于A,上面有一句话很重要由一个调控系统内全部对象的外界实体将其所依赖的对象的引用传递给它,我的理解,在B类中使用A类的实例,而不是继承A类。segmentfault

对面向对象了解的同窗应该了解,面向对象7大原则:后端

  1. 单一职责
  2. 开闭原则
  3. 里氏替换
  4. 依赖倒置
  5. 接口隔离
  6. 迪米特法则
  7. 组合聚合复用原则

详细解释参照:面向对象之七大基本原则(javaScript)设计模式

然而使用依赖注入的事为了下降代码的耦合程度,提升代码的可拓展性。以上都是一些面向对象的思想,咱们参考一下以上最重要的几个原则,层模块不该该依赖低层模块。两个都应该依赖抽象,抽象不该该依赖具体实现,具体实现应该依赖抽象。api

// 球队信息不依赖具体实现
// 面向接口即面向抽象编程
class Fruit {
    constructor(name) {
        this.name = name
    }
}
class Tropical {
    // 此处的参数,是teamInfo的一个实例,不直接依赖具体的实例
    // 面向抽象
    constructor(fruit) {
        this.fruit = fruit;
    }
    info() {
        console.log(this.fruit.name)
    }
}
// 将依赖关系放到此处来管理,控制权也放到此处
// Tropical和Fruit之间再也不有直接依赖
// 本来直接掌握Fruit控制权的Tropical再也不直接依赖
// 将依赖控制,落在此处(第三方模块专门管理)即为控制反转
var ym = new Tropical(new Fruit('香蕉'))
ym.info()
var kobe = new Tropical(new Fruit('菠萝'))
kobe.info()

依赖注入的做用

初始化被依赖的模块架构

若是不经过依赖注入模式来初始化被依赖的模块,那么就要依赖模块本身去初始化了
那么问题来了:依赖模块就耦合了被依赖模块的初始化信息了框架

注入到依赖模块中

被依赖模块已经被其余管理器初始化了,那么依赖模块要怎么获取这个模块呢?

有两种方式:

  • 本身去问
  • 别人主动给你

没用依赖注入模式的话是1,用了以后就是2

想一想,你须要某个东西的时候,你去找别人要,你须要提供别人什么信息?最简单的就是那个东西叫什么,即你须要提供一个名称。因此,方式1的问题是:依赖模块耦合了被依赖模块的名称还有那个别人而方式2解决了这个问题,让依赖模块只依赖须要的模块的接口。

依赖注入的优势

依赖注入下降了依赖和被依赖类型间的耦合,在修改被依赖的类型实现时,不须要修改依赖类型的实现,同时,对于依赖类型的测试。依赖注入方式,能够将代码耦合性降到最低,并且各个模块拓展不会互相影响,

  1. 实现数据访问层,也就是前端你的数据请求层
  2. 模块与接口重构,依赖注入背后的一个核心思想是单一功能原则,这意味着这些对象在系统的任何地方均可以重用。
  3. 随时增长单元测试,把功能封装到整个对象里面会致使自动测试困难或者不可能。将模块和接口与特定对象隔离,以这种方式重构能够执行更先进的单元测试。

Vue中使用

上面写的例子也只是对依赖注入见单的使用,在项目过程当中每每就不是这么简单了,确定不会向例子这么简单,而是很复杂很庞大的一个项目。项目中分为各类各样的模块,这种状况又改如何处理?在JavaScript中常见的就是依赖注入。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来讲,即由容器动态的将某种依赖关系注入到组件之中。

前端项目中并不像后端同样,各类各样的类,虽然前端能够写class,如果React项目的话,还会好不少,因为其框架使用,所有是基于class可是在vue项目中,又应该怎么具体体现呢?页面中的业务也是能够做为类存在最终注入到Vue页面中,最终完成业务逻辑。

o_7A56115D-CE2F-43e4-A824-35975D35502F.png

经过依赖注入到底想要达到到什么效果呢,依赖注入最终想要达成的效果则是,页面的表现与业务相脱离,从本质上来讲,页面的展示形式与业务逻辑其实没有根本联系的。若使用这种依赖注入的形式,则能够轻松的把业务和页面表现分离开,页面更加的专一于展现,而所注入的东西则更加的专一于业务的处理。项目也则会变得容易维护。

index.vue

<template>
  <div>
    <el-button @click="getList"
              :loadding="loadding">获取表格数据</el-button>
    <ul>
      <li v-for="(item,index) of list"
          :key="index">{{item}}</li>
    </ul>
  </div>
</template>
<script>
import operation from "@/business/index/Operation.js";
export default {
  data() {
    return {
      list: [],
      query:{},
      loadding:false
    }
  },
  methods:{
    async getList(){
      let {query} = this;
      this.loadding = true;
      try{
        this.list = await operation.getData.call(this,query);
      }catch(error){
        console.log(error)
      }
      this.loadding =false;
    }
  }
}
</script>
<style>
@import "@/style/index.vue";
</style>

operations.js

import request from "@/api/errorList/index.js";
class Operation {
    async getData(query){
        //  this 指向Vue实例
        try {
            let res = await request.getErrorList(query);
            let {list} = res;
            //  这里能够对数据进行二次处理
            //  写一些其余业务
            Promise.resolve(list);
        }catch(error){
            Promise.reject(error);
        }
    }
};
export default new Operation();

上面也是在项目中的一个简单的应用,使页面表现数据请求与数据处理,业务相脱离,让项目变得更加容易维护。

控制反转这里控制权从使用者自己转移到第三方容器上,而非是转移到被调用者上,这里须要明确不要疑惑。控制反转是一种思想,依赖注入是一种设计模式。

依赖注入最终想要达到的目的,首先得为模块依赖提供抽象的接口,下来应该可以注册依赖关系
在注册这个依赖关系后有地方存储它,存储后,咱们应该把被依赖的模块注入依赖模块中,注入应该保持被传递函数的做用域,被传递的函数应该可以接受自定义参数,而不只仅是依赖描述。

总结

JavaScript中依赖注入的概念不像Java中被常常提到,主要缘由是在js中很容易就实现了这种动态依赖。其实咱们大部分人都用过依赖注入,只是咱们没有意识到。即便你不知道这个术语,你可能在你的代码里用到它百万次了。但愿这篇文章能加深你对它的了解。

须要注意的是,依赖注入只是控制反转的一种实现方式,正确的依赖管理是每一个开发周期中的关键过程。JavaScript 生态提供了不一样的工具,做为开发者的咱们应该挑选最适合本身的工具。

相关文章
相关标签/搜索