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,但它仍然是一种有趣的模式,探索它的实现也是有现实意义(前端后端化条件下),可以更好的理解其含义,把握好使用的场景。
参考链接