Vue.js的IoC容器模式探索

IoC概念闡述

  • IoC(Inversion of Control),意爲控制反轉,不是什麼技術,而是一種設計思想。==Ioc意味着將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制==。
  • 借用《spring 揭祕》的一張圖對IOC的概念闡述
  • image
  • 下面咱們將嘗試在Vue.js中實現IoC容器模式,他的基本構造以下圖

vue-ioc概念圖

代碼實現

- service-container容器

<!--service-container.js-->
const RepositoryInterface = {
  find () {},
  list () {}
}

function bind (repositoryFactory, Interface) {
  return {
    ...Object.keys(Interface).reduce((prev, method) => {
      const resolveableMethod = async (...args) => {
        const repository = await repositoryFactory()
        return repository.default[method](...args)
      }
      return { ...prev, [method]: resolveableMethod }
    }, {})
  }
}

export default {
  get productRepository () {
    // Delay loading until a method of the repository is called.
    return bind(() => import('@/views/ioc/product'), RepositoryInterface)
  },
  get userRepository () {
    // Load the repository immediately when it's injected. const userRepositoryPromise = import('@/views/ioc/user') return bind(() => userRepositoryPromise, RepositoryInterface) } } 複製代碼
  • 如上代碼所示,有一個bind()輔助函數,該函數接受一個接口(這是一個普通的對象,其中包含咱們真實存儲庫的每一個方法的僞方法)以及要動態解析的存儲庫的生成方法,以及它返回一個包含原始存儲庫的全部方法的對象。
  • 實現了按需加載服務,不會一次加載全部的服務,想象一下,我只使用A服務,結果將A服務之外的其餘服務都加載了,這是不合理的。

UserListing接口模擬

// Usually a third party API.
const api = Promise.resolve([
  {
    id: 1,
    name: 'Antonia'
  },
  {
    id: 2,
    name: 'Anton'
  }
])

export default {
  async find (id) {
    const result = await api
    return result.find(x => x.id === id)
  },
  async list () {
    return api
  }
}

複製代碼

product 接口模擬

// Usually a third party API.
const api = Promise.resolve([
  {
    id: 1,
    title: 'Some stuff'
  },
  {
    id: 2,
    title: 'Some other stuff'
  }
])

export default {
  async find (id) {
    const result = await api
    return result.find(x => x.id === id)
  },
  async list () {
    return api
  }
}

複製代碼

UserListing組件

<template>
  <ul>
    <li v-for="user in users" :key="user.id">{{ user.name }}</li>
  </ul>
</template>

<script>
  export default {
    name: 'UserListing',
    inject: ['userRepository'],
    data () {
      return { users: [] }
    },
    async created () {
      this.users = await this.userRepository.list()
    }
  }
</script>

複製代碼

ProductListing組件

<template>
  <ul>
    <li v-for="product in products" :key="product.id">{{ product.title }}</li>
  </ul>
</template>

<script>
  export default {
    name: 'ProductListing',
    inject: ['productRepository'],
    data () {
      return { products: [] }
    },
    async created () {
      this.products = await this.productRepository.list()
    }
  }
</script>

複製代碼

IOC 測試頁面

<template>
  <div id="app">
    <h2>Products</h2>
    <ProductListing/>

    <h2>Users</h2>
    <UserListing/>
  </div>
</template>

<script>
  import ProductListing from './ProductListing'
  import UserListing from './UserListing'

  export default {
    components: {
      ProductListing,
      UserListing
    }
  }
</script>

複製代碼

總結

  • 一般來說,IoC容器模式在JavaScript這樣的語言中實際上沒那麼有用。爲何?由於你不須要它來得到許多其餘語言如Java、PHP所帶來的好處。例如。咱們能夠使用高階函數的概念經過參數將依賴關係傳遞給函數(或經過Vue.js組件中的props)。
  • 使用JavaScript和Vue.js構建可伸縮應用程序可能也不須要IoC,但它仍然是一種有趣的模式,探索它的實現也是有現實意義(前端後端化條件下),能夠更好的理解其含義,把握好使用的場景。

參考連接

相關文章
相關標籤/搜索