一般来说,在我的Angular / TypeScript应用程序中,我倾向于使用“控制器为”语法。
然而,对于我正在研究的CRUD屏幕,我发现自己偏离了这一点。这样我就可以利用$watchCollection
/检查更改等等,我发现自己使用的是优秀的小伙子@basarat here建议的模式。也就是说,在视频中(在Angular中将“控制器作为”语法之前)@basarat创建了一个变量,表示$scope
上名为vm
的控制器。与在视图中使用“controller as vm”的方式相同,您仍然可以使用vm.myProperty
/ vm.myFunction()
样式语法与模型进行交互。
所以,控制器看起来像这样:
module controllers {
"use strict";
interface sageEditRouteParams extends ng.route.IRouteParamsService {
id: number;
}
interface sageEditScope extends ng.IScope {
vm: SageEdit;
}
class SageEdit {
log: loggerFunction;
sage: sage;
title: string;
private _hasChanges: boolean;
static $inject = ["$routeParams", "$scope", "common", "datacontext"];
constructor(
private $routeParams: sageEditRouteParams,
private $scope: sageEditScope,
private common: common,
private datacontext: datacontext
) {
this.sage = undefined;
this.title = "Sage Edit";
this.log = common.logger.getLogFn(controllerId);
$scope.vm = this;
$scope.$watchCollection("vm.sage", (newSage: sage, oldSage: sage) => {
if (newSage && oldSage) {
this._hasChanges = true;
}
});
this.activate();
}
// Prototype methods
activate() {
var id = this.$routeParams.id;
var dataPromises: ng.IPromise<any>[] = [this.getSage(id)];
this.common.activateController(dataPromises, controllerId)
.then(() => {
this.log("Activated Sage Edit View");
this.title = "Sage Edit: " + this.sage.name;
});
}
getSage(id: number) {
return this.datacontext.sage.getById(id).then(data => {
this.sage = data;
this._hasChanges = false;
});
}
get hasChanges(): boolean {
return this._hasChanges;
}
}
var controllerId = "sageEdit";
angular.module("app").controller(controllerId, SageEdit);
}
这样的观点:
<section class="mainbar" ng-controller="sageEdit">
<section class="matter">
<div class="container-fluid">
<div>
<button class="btn btn-info"
ng-click="vm.cancel()"
ng-disabled="!vm.canSave">
<i class="fa fa-undo"></i>Cancel
</button>
<button class="btn btn-info"
ng-click="vm.save()"
ng-disabled="!vm.canSave">
<i class="glyphicon glyphicon-save"></i>Save
</button>
<span ng-show="vm.hasChanges"
class="dissolve-animation ng-hide">
<i class="glyphicon glyphicon-asterisk text-info"></i>
</span>
</div>
<div class="widget wgreen">
<div data-cc-widget-header title="{{vm.title}}"></div>
<div class="widget-content form-horizontal">
<div class="form-group">
<label class="col-xs-12 col-sm-2">Name</label>
<input class="col-xs-12 col-sm-9" ng-model="vm.sage.name" />
</div>
<div class="form-group">
<label class="col-xs-12 col-sm-2">Username</label>
<input class="col-xs-12 col-sm-9" ng-model="vm.sage.userName" />
</div>
<div class="form-group">
<label class="col-xs-12 col-sm-2">Email</label>
<input class="col-xs-12 col-sm-9"
type="email"
ng-model="vm.sage.email" />
</div>
</div>
</div>
</div>
</section>
</section>
我正在组合起来似乎工作得很好,但我想把它放在那里并得到一些其他观点。是吗:
我做了一点挖掘,但没有找到任何结论。
答案 0 :(得分:6)
对于
$scope.$watchCollection("vm.sage", (newSage: sage, oldSage: sage) => {
您也可以轻松实现重构:
$scope.$watchCollection(()=>this.sage, (newSage: sage, oldSage: sage) => {
在某些情况下,当您尝试查看foo.bar
之类的内容foo
尚未定义时,您可以使用安全包装函数safeWatch(()=>this.foo.bar)
:
function safeWatch<T extends Function>(expression: T) {
return () => {
try {
return expression();
}
catch (e) {
return null;
}
};
}
这正是角度正在为你做的事情。即$scope.vm = instance
(其中vm == indentifier
)所以它们是等价的