打印稿,Angular设计——传递依赖的另一种方式

typescript & angular design - alternative way of passing dependencies

本文关键字:依赖 另一种 方式 Angular 设计 打印稿      更新时间:2023-09-26

大家好!

TL,博士我能把angular依赖传递给TypeScript模块/类吗,这样这些依赖就不会成为类对象的属性——相反,它们可以通过作用域函数参数获得?

我知道在angular/typescript中声明东西的推荐方式是在TS模块中创建一个TS类,并将其作为angular服务发布,因为:
  • 不能是工厂
  • 有模块是好的
  • 类(与普通函数相比)可以用来检查typescript
  • 中的编译时类型

这种方法的一个例子如下:

/// <reference path="../../project.d.ts" />
module project.core.services {
  export class UiRoutes {
    static $inject = ['$state'];
    constructor(private $state: angular.ui.IStateService) {
    }
    public reloadCurrentView(): void {
      this.$state.go(this.$state.current.name, this.$state.params, {
        reload: true
      });
    }
  }
}
project.core.CoreModule.service('UiRoutes', project.core.services.UiRoutes);

无论如何,这种方法有一个很大的问题,那就是——我被迫将所有的角依赖传递给类构造函数,使它们成为对象属性(随处可用,而不是封装——因为如果对象是可访问的,那么它的所有属性都是可访问的)。

作为替代方案,有Backbone.js + Require.js示例:

define(['jquery', 'use!backbone','models/model'], function($, Backbone, Model){
  View = Backbone.View.extend({
    //...
  });
  return new View();
});

中,如你所见,jquery、骨干和一些内部的东西是可用的,但它没有保存为对象属性——它通过作用域可用。这是纯粹自然的JavaScript做事方式——通过作用域函数参数传递东西。在这种情况下,您可以封装更多的东西,并且代码变得不那么冗长。而且,最主要的是,有选择而不是被迫遵循唯一正确的规则是件好事。

现在我知道了backbone和angular是不同的,而且,DI和require.js是完全不同的,等等等等。

我想要的是一个例子(或者只是一个设计),它允许我指定所有的angular依赖项,并使它们可以被TypeScript模块/类访问,但不能使它们成为类对象的属性。毕竟,这在纯AngularJS(没有TypeScript)中是可能的,所以在使用TypeScript时也是可能的。


如果不清楚,我很乐意提供更好的问题描述(请评论)。但如果我对"这不是你想要的,但它对我有用,试试这个"这样的答案不感兴趣:)如果答案是"不,那是不可能的",那么我希望你能证明和/或解释为什么。

因为如果对象是可访问的那么它的所有属性都是可访问的

从运行时的角度来看,这可能是正确的,但是运行时的角度并不是唯一重要的。如果你用的是TypeScript,并把注入的服务标记为private,那么没有人会访问这些东西,除非它们是恶意的。而且很有可能你的代码已经无法抵御运行时环境中的恶意行为者了(通常情况下,想要破坏你的应用的人可以注入任何Angular服务,并用他们自己的服务覆盖它的属性)。

因此,在这方面,最好的做法是不要关心对象上某处发生的事情与闭包中某处发生的事情。

现在我知道了backbone和angular是不同的,而且,DI和require.js是完全不同的,等等等等。

继续往下说,这里的一个相关区别是,你的requirejs模块实际上是一个单例模块,而你的Angular类通常不是(它们中的大多数可能是控制器)。

我们需要回到对象和闭包的区别来理解为什么这很重要。如果你想在注入的服务上拥有闭包隐私(因为编译时的隐私由于某种原因不够好),那么你的对象的每个实例都需要自己的一组子闭包,以便能够访问那些闭包值。

当对象有很多实例时,为对象的每个实例重复函数闭包会导致很大的性能损失。这意味着更多的分配、更大的内存压力、更多的时间用于清理GC中的内容、更多的时间用于标记、清理或在GC中重新计数、更少的引用局部性、更低的JIT效率等等。这就是为什么TypeScript和其他语言没有给你现成的基于闭包的类。

现在你说"但是我的服务是单例的!"你是对的。单例可以像这样写成闭包:

module project.core.services {
  export function UiRoutes($state: angular.ui.IStateService) {
    function go() {
      $state.go(/* etc*/);
    }
    function other() { }
    function foo() { }
    return {
      go,
      other,
      foo
    }
  }
}