Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS/Typescript集成模式-作用域方法_Javascript_Angularjs_Typescript - Fatal编程技术网

Javascript AngularJS/Typescript集成模式-作用域方法

Javascript AngularJS/Typescript集成模式-作用域方法,javascript,angularjs,typescript,Javascript,Angularjs,Typescript,我正在尝试改变我编写AngularJS应用程序的方式,从简单的javascript改为使用TypeScript作为预处理器 在涉及作用域方法调用时,我正在努力协调这两种方法 为了说明的目的,让我们考虑常用菜单的用例;我希望突出显示当前显示的特定菜单项。HTML模板如下所示: <ul class="nav navbar-nav"> ... <li ng-class="{active: isSelected('/page1')}"><a href="#/page

我正在尝试改变我编写AngularJS应用程序的方式,从简单的javascript改为使用TypeScript作为预处理器

在涉及作用域方法调用时,我正在努力协调这两种方法

为了说明的目的,让我们考虑常用菜单的用例;我希望突出显示当前显示的特定菜单项。HTML模板如下所示:

<ul class="nav navbar-nav">
  ...
  <li ng-class="{active: isSelected('/page1')}"><a href="#/page1">Page 1</a></li>
  ...
</ul>
这个匿名函数声明似乎并不真正尊重更传统的TypeScript类模型。在typescript中,我发现自己很想写以下内容:

export interface MenuScope extends ng.IScope {
    isSelected(path: String): boolean;
}

export class MenuController {

    location: ng.ILocationService;

    scope: MenuScope;

    constructor($scope: MenuScope, $location: ng.ILocationService) {
        this.scope = $scope;
        this.location = $location;

        this.scope.isSelected = function(path) { return this.isSelected(path) }.bind(this);
    }

    isSelected(path: String): boolean {
        return this.location.path().substr(0, path.length) == path;
    }
}
在这种情况下,
isSelected
属于控制器,而不是范围。这似乎是明智的。但是,作用域和控制器之间的“链接”仍然依赖于匿名方法

更糟糕的是,我必须显式绑定
this
的上下文,以确保我可以编写
this.location
来访问
isSelected()实现中的位置服务


我希望从TypeScript中获得的好处之一是更清晰的代码编写方式。通过绑定的匿名函数进行的间接寻址似乎与此相反。

您不应该将
$scope
作为变量存储在
This
中,而是将
This
用作
$scope
,方法是这样做
$scope.vm=This
您无法避免this.location=$location
,因为这是TypeScript的语法


顺便说一句,您应该对依赖项使用$inject。

我们正在考虑类似的转换(例如,从Javascript到Angular的Typescript)。在我们开始实施时,有些事情(比如您的示例)看起来非常奇怪。最快的方法是使用
控制器作为
语法。这样,就可以直接在控制器上公开方法

<!-- use controller as syntax -->
<div ng-controller="MenuController as menu">
<ul class="nav navbar-nav">
  ...
  <li ng-class="{active: menu.isSelected('/page1')}"><a href="#/page1">Page 1</a></li>
  ...
</ul>
</div>
由于angular负责实例化控制器,因此返回类型
any
无关紧要。但是如果你的$scope方法有错误,你可能会被抓住

要解决这个问题,您可以进一步使用
controller as
语法。下面的示例不允许您自己实际更新控制器(例如,new MenuController($location)将因
而失败,只能使用new关键字调用void函数,但这是可以忽略的,因为angular为您处理实例化

export interface IMenuController {
    isSelected(path: string): boolean;
}
export function MenuController($location: ng.ILocationService): IMenuController {
    var self:IMenuController = this;

    self.isSelected = function(path:string): boolean {
      return $location.path().substr(0, path.length) == path;
    }

    // explicitly return self / this to compile
    return self;
}

TL-DR:我非常喜欢类型的编译时检查,并且喜欢使用类的概念。然而,我不认为它完全符合Angular 1.x模型。这似乎是为Angular2设计的。使用强类型函数代替Angular 1.x。

这是一个带有控制器和服务的简单应用程序。我在项目中使用此样式:

/// <reference path="typings/angularjs/angular.d.ts" />
module App {
    var app = angular.module("app", []);
    app.controller("MainController as vm", Controllers.MainController);
    app.service("backend", Services.Backend);
}

module App.Controllers {
    export class MainController {
        public persons: Models.Person[];

        static $inject = ["$location", "backend"];
        constructor(private $location: ng.ILocationService, private backend: Services.Backend) {
            this.getAllPersons();
        }

        public isSelected(path: string): boolean {
            return this.$location.path().substr(0, path.length) == path;
        }

        public getAllPersons() {
            this.backend.getAllPersons()
                .then((persons) => {
                    this.persons = persons;
                })
                .catch((reason) => console.log(reason));
        }
    }
}

module App.Services {
    export class Backend {
        static $inject = ["$http"];
        constructor(private $http: ng.IHttpService) { }

        public getAllPersons(): ng.IPromise<Models.Person[]> {
            return this.$http.get("api/person")
                .then((response) => response.data);
        }
    }
}

module App.Models {
    export interface Person {
        id: number;
        firstName: string;
        lastName: string;
    }
}
//
模块应用程序{
var-app=angular.module(“app”,[]);
app.controller(“MainController作为vm”,Controllers.MainController);
app.service(“后端”,Services.backend);
}
模块应用程序控制器{
导出类主控制器{
公众人物:模特。人物[];
静态$inject=[“$location”,“backend”];
构造函数(私有$location:ng.ILocationService,私有后端:Services.backend){
这个.getAllPersons();
}
公共isSelected(路径:字符串):布尔值{
返回此.$location.path().substr(0,path.length)=path;
}
公众人物(){
this.backend.getAllPersons()
.然后((人)=>{
这个人=人;
})
.catch((原因)=>console.log(原因));
}
}
}
模块应用程序服务{
导出类后端{
静态$inject=[“$http”];
构造函数(私有$http:ng.IHttpService){}
public getAllPersons():ng.IPromise{
返回此。$http.get(“api/人”)
.然后((响应)=>response.data);
}
}
}
模块应用程序模型{
出口接口人员{
id:编号;
名字:字符串;
lastName:string;
}
}
  • 我有应用程序模块、控制器模块、服务模块和模型模块
  • 控制器定义为类,但必须通过
    控制器作为
    语法注册到应用程序。因此,您在类中定义的所有内容都可以通过视图(控制器范围)中的
    vm
    访问。这里有
    persons
    isSelected
    getAllPersons
  • 您可以通过
    static$inject
    注入每一个可注入的元素,这是一个
    字符串[]
    ,然后将它们分别添加为构造函数参数。此角色在定义服务时也可用,并且可以缩小
  • 您还可以将
    $scope
    注入控制器类,以访问特定于作用域的工具,如
    $apply
    on
  • 您可以定义服务来将它们定义为类,而不是定义工厂
  • 在服务中注入与在控制器中注入相同
  • 您可以将http调用的返回类型定义为
    ng.IPromise
    ,然后返回
    response.data
    ,以确保返回方法的类型只是实体,而不是与http相关的数据
  • 在TAX中使用“Controller as vm”将起作用,然后您应该调用vm.IsSelected请参阅Angular Style Guide(由Angular团队提供)的部分,并尽可能避免使用
    $scope
    export interface IMenuController {
        isSelected(path: string): boolean;
    }
    export function MenuController($location: ng.ILocationService): IMenuController {
        var self:IMenuController = this;
    
        self.isSelected = function(path:string): boolean {
          return $location.path().substr(0, path.length) == path;
        }
    
        // explicitly return self / this to compile
        return self;
    }
    
    /// <reference path="typings/angularjs/angular.d.ts" />
    module App {
        var app = angular.module("app", []);
        app.controller("MainController as vm", Controllers.MainController);
        app.service("backend", Services.Backend);
    }
    
    module App.Controllers {
        export class MainController {
            public persons: Models.Person[];
    
            static $inject = ["$location", "backend"];
            constructor(private $location: ng.ILocationService, private backend: Services.Backend) {
                this.getAllPersons();
            }
    
            public isSelected(path: string): boolean {
                return this.$location.path().substr(0, path.length) == path;
            }
    
            public getAllPersons() {
                this.backend.getAllPersons()
                    .then((persons) => {
                        this.persons = persons;
                    })
                    .catch((reason) => console.log(reason));
            }
        }
    }
    
    module App.Services {
        export class Backend {
            static $inject = ["$http"];
            constructor(private $http: ng.IHttpService) { }
    
            public getAllPersons(): ng.IPromise<Models.Person[]> {
                return this.$http.get("api/person")
                    .then((response) => response.data);
            }
        }
    }
    
    module App.Models {
        export interface Person {
            id: number;
            firstName: string;
            lastName: string;
        }
    }