上层设计

  • rpc通信
  • 进行(主进程,渲染进程,插件进程)
  • vscode如何暴露给插件
  • 插件的设计

运行时的设计

  • Service模式
  • 依赖注入

一些设计

  • event设计
  • TreeContext设计

一些重点Service

  • ListService
  • IInstantiationService
  • CommandService

typescript的用法

  • 装饰器

优秀的设计

  • 程序的健壮性(interface)
  • 程序的复用和扩展性(TreeView)

一些反思和质疑

  • 这种面向对象渲染模式是否好?写起来效率太低了

上层设计

rpc通信

进程管理

vscode如何暴露给插件

插件的设计

运行时设计

Service模式

看下fileAction中使用到service和accesor的

  1. // 获取explorerContext
  2. function getContext(listWidget: ListWidget, viewletService: IViewletService): IExplorerContext {
  3. // These commands can only be triggered when explorer viewlet is visible so get it using the active viewlet
  4. const tree = <ITree>listWidget;
  5. const stat = tree.getFocus();
  6. const selection = tree.getSelection();
  7. // Only respect the selection if user clicked inside it (focus belongs to it)
  8. return { stat, selection: selection && selection.indexOf(stat) >= 0 ? selection : [], viewletState: (<ExplorerViewlet>viewletService.getActiveViewlet()).getViewletState() };
  9. }
  10. // 注册新建文件的命令,右键会通过commandService调用此命令
  11. CommandsRegistry.registerCommand({
  12. id: NEW_FILE_COMMAND_ID,
  13. handler: (accessor) => {
  14. return openExplorerAndRunAction(accessor, NewFileAction);
  15. }
  16. });
  17. // 新建文件时的处理逻辑
  18. function openExplorerAndRunAction(accessor: ServicesAccessor, constructor: IConstructorSignature2<ITree, ExplorerItem, Action>): TPromise<any> {
  19. const instantationService = accessor.get(IInstantiationService);
  20. const listService = accessor.get(IListService);
  21. const viewletService = accessor.get(IViewletService);
  22. const activeViewlet = viewletService.getActiveViewlet();
  23. let explorerPromise: Thenable<IViewlet> = Promise.resolve(activeViewlet);
  24. if (!activeViewlet || activeViewlet.getId() !== VIEWLET_ID) {
  25. explorerPromise = viewletService.openViewlet(VIEWLET_ID, true);
  26. }
  27. return explorerPromise.then((explorer: ExplorerViewlet) => {
  28. const explorerView = explorer.getExplorerView();
  29. if (explorerView && explorerView.isVisible() && explorerView.isExpanded()) {
  30. explorerView.focus();
  31. //
  32. const explorerContext = getContext(listService.lastFocusedList, viewletService);
  33. const action = instantationService.createInstance(constructor, listService.lastFocusedList, explorerContext.stat);
  34. return action.run(explorerContext);
  35. }
  36. return undefined;
  37. });
  38. }

```

ServicesAccessor?

就像window的全局变量,供我们来访问各种service。在command回调参数中有个accesor。

Service模式?

是什么,特征?哪些服务该设计成service?设计有何益处,即如果没有呢?

  • 是什么?

特征和使用

全局的只有一个实例,command会掉参数有个accesor参数,可以通过accesor获取到唯一的service。

  • 哪些服务该设计成service

  • 设计的益处和原因?

依赖注入可以注入service

如果不用service模式呢?

依赖注入

为什么需要依赖注入?TODO

依赖注入的实现

  • 类实例化时都通过 instantiationService.createInstance(Clazz) 初始化
  • construcrot上通过@符号,标记需要注入的service

一些重点Service

IInstantiationService

依赖注入的实现

所有实例化都通过调用此的createInstance方法来进行实例化。

因为需要依赖注入,初始化前检查constructor上的注入标记。

src/vs/platform/instantiation/common/instantiationService.ts 见此文件

ServicesAccessor

访问所有的service,在command的回调参数中

CommandService

命令

ListService

所有list都注册在这里,可获取最后active的list

ViewletService

一些设计

事件设计

TreeContext

Typescript应用

优秀的设计

程序的健壮性

所有都用interface进行了定义,类定义,参数定义等等。

只要写的有问题就会报错

程序的复用和扩展性

TreeView将逻辑暴露给Context

ViewItem将内容渲染交给renderer

一些质疑和思考

这种面向对象渲染模式是否好?

  • 修改有点太复杂了

  • 渲染很多都是局部更新,添加class等,局部状态?