IoC概念闡述
- IoC(Inversion of Control),意爲控制反轉,不是什麼技術,而是一種設計思想。==Ioc意味着將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制==。
- 借用《spring 揭祕》的一張圖對IOC的概念闡述
-
- 下面咱們將嘗試在Vue.js中實現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,但它仍然是一種有趣的模式,探索它的實現也是有現實意義(前端後端化條件下),能夠更好的理解其含義,把握好使用的場景。
參考連接