Skip to content

父组件获取子组件服务

假设如下场景

父组件是 ParentComp,绑定的服务是 ParentService。

父组件下依赖的子组件有 ChildComp1、ChildComp2、ChildComp3...,对应的服务有 ChildService1、ChildService2、ChildService3...

父组件获取子组件的服务

useService 负责从当前组件和父组件以及祖先组件中查找指定的服务。
findService 负责从当前组件的子组件/子孙组件中查找指定的服务。

需要明确的是 findService 方法是必要的,因为父子组件的生命周期不一致,所以不会在父组件的服务中持有子组件服务的实例对象,而是应该实时查询子组件服务。

实现方案

理论上可选的方案有如下 4 种:

方案 1:

ts
// 这里的this.container是当前服务关联的容器
this.container.getServiceFromChild(ChildServiceToken);

方案 2:

ts
// 这里的this.component是当前服务绑定的组件
this.component.getServiceFromChild(ChildServiceToken);

方案 3:

ts
// 这里的getServiceFromChild是全局工具方法
getServiceFromChild(ChildServiceToken, this.component);

方案 4:

ts
// 这里的FIND_CHILD_SERVICE是本库提供的token
const findService = useService(FIND_CHILD_SERVICE);
const service = findService(ChildServiceToken);

最终确定的实现方案是方案 4,也就是首先利用 useService 获取 findService 工具方法,然后调用 findService 方法查找子组件的服务。 这个访问的优点是不需要暴露 container 和 component,而且可以同时在组件内使用和服务中使用。

实现逻辑可以参考这里vuejs/test-utils#findComponent

使用场景

场景 1:在组件中使用

vue
<script lang="ts" setup>
import { getCurrentInstance } from 'vue';
import { FIND_CHILD_SERVICE, Token, useService } from '@kaokei/use-vue-service';
const token = new Token<ChildServiceType>('child service name');

function handleClickEvent() {
  const findService = useService(FIND_CHILD_SERVICE);
  const childService = findService(token);
  childService.doSomthing();
}
</script>

场景 1:在服务中使用

ts
import {
  Inject,
  FIND_CHILD_SERVICE,
  Token,
  useService,
} from '@kaokei/use-vue-service';
const token = new Token<ChildServiceType>('child service name');

class DemoService {
  public handleClickEvent() {
    const findService = useService(FIND_CHILD_SERVICE);
    const childService = findService(token);
    childService.doSomthing();
  }
}