我正在注册" $ routeChangeSuccessEvent"通过设置回调函数来自Angularjs。当事件被引发时,我无法通过"这个"来访问我的控制器实例。当前这个实例是未定义的。
我完整的TypeScript代码:
export class Ctlr {
static $inject = ["$rootScope","$route"];
constructor(private $scope: ng.IRootScopeService) {
this.Scope = $scope;
this.Title = "";
//this.Scope.$on("$routeChangeSuccessEvent", this.onRouteChangeStart);
this.RegisterEvents();
}
private RegisterEvents(): void {
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
//this is undefined
console.log(this);
});
}
public Scope: ng.IScope;
public Title: string;
public onRouteChangeStart(event: ng.IAngularEvent, args: any) {
//this is undefined
this.Title = args.$$route.name);
}
}
}
我可以通过以下方式访问Title属性:
private RegisterEvents(): void {
var ref = this.Title;
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
ref = args.$$route.name;
});
}
但这不是一个真正的解决方案,因为angularJS不会更新其视图。似乎我没有抓住正确的参考。如果那不可能那么整个angularjs事件似乎都没有用 - 这是不可能的?
我也没有找到关于这种奇怪行为的话题。这个问题有解决方案吗?
答案 0 :(得分:3)
触发回调时范围会发生变化,这就是this
未定义的原因。
你做的另一个例子:
var ref = this.Title;
实际上只是创建一个Title
的-copy-,因为它是一个原始类型(字符串)。这就是为什么它也没有用的原因。更新ref
不会更新this.Title
。
通常的解决方法是将定义开始为:
var vm = this;
...
private RegisterEvents(): void {
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
//this is undefined
console.log(vm);
});
}
所以,不要在任何地方使用this
,而是使用vm
。请注意,vm
可以根据需要命名。重要的一部分是在this
范围内捕获对this
的引用,其中this
是您要在回调中使用的内容。这是有效的,因为bind
不是一种基本类型,因为它是一个对象,而不是复制它,它需要一个引用。
您的另一个选择是使用可以应用于任何函数的this
,此函数实质上告诉JavaScript $scope.$on("SomeEventHere", someCallbackFunction.bind(this));
将等同于什么。 E.g。
var something = this;
这是您在此处使用的偏好问题,但通常我会看到人们使用import smart_open
import io
import csv
testDict = [{
"fieldA": "8",
"fieldB": None,
"fieldC": "888888888888"},
{
"fieldA": "9",
"fieldB": None,
"fieldC": "99999999999"}]
fieldnames = ['fieldA', 'fieldB', 'fieldC']
f = io.StringIO()
with smart_open.smart_open('s3://dev-test/bar/foo.csv', 'wb') as fout:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
fout.write(f.getvalue())
for row in testDict:
f.seek(0)
f.truncate(0)
writer.writerow(row)
fout.write(f.getvalue())
f.close()
方法。
答案 1 :(得分:0)
那是因为这总是指它的父亲,现在是这个功能。所以,如果你想要,你可以这样做:
-(void)createCollisionAreas
{
if (_tileMap)
{
TMXObjectGroup *group = [_tileMap groupNamed:@"ContactZone"]; //Layer's name.
//Province gateway.
NSDictionary *singularObject = [group objectNamed:@"msgDifferentProvince"];
if (singularObject)
{
CGFloat x = [singularObject[@"x"] floatValue];
CGFloat y = [singularObject[@"y"] floatValue];
CGFloat w = [singularObject[@"width"] floatValue];
CGFloat h = [singularObject[@"height"] floatValue];
SKSpriteNode *object = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(w, h)];
object.name = @"provinceGateway";
object.position = CGPointMake(x + w/2, y + h/2);
object.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(w, h)];
object.physicsBody.categoryBitMask = terrainCategory;
object.physicsBody.contactTestBitMask = playerCategory;
object.physicsBody.collisionBitMask = 0;
object.physicsBody.dynamic = NO;
object.physicsBody.friction = 0;
object.hidden = YES;
[_backgroundLayer addChild:object];
}
/*More code written below. Too lazy to copy & paste it all*/
}
-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody; //Create 2 placeholder reference's for the contacting objects.
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) //If bodyA has smallest of 2 bits...
{
firstBody = contact.bodyA; //...it is then the firstBody reference [Smallest of two (category) bits.].
secondBody = contact.bodyB; //...and bodyB is then secondBody reference [Largest of two bits.].
}
else //This is the reverse of the above code (just in case so we always know what's what).
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
/**BOUNDARY contacts*/
if ((firstBody.categoryBitMask == noGoCategory) && (secondBody.categoryBitMask == playerCategory))
{
//Boundary contacted by player.
if ([_backgroundLayer childNodeWithName:@"bounds"])
{
NSLog(@"Player contacted map bounds.");
}
if ([_backgroundLayer childNodeWithName:@"nogo"])
{
NSLog(@"Player can't go further.");
}
if ([_backgroundLayer childNodeWithName:@"provinceGateway"])
{
NSLog(@"Another province is ahead. Can't go any further.");
}
if ([_backgroundLayer childNodeWithName:@"slope"])
{
NSLog(@"Player contacted a slope.");
}
}
答案 2 :(得分:0)
你可以重新绑定这个变量:
this.Scope.$on("$routeChangeSuccessEvent",this.onRouteChangeStart.bind(this));
答案 3 :(得分:0)
如其他解决方案中所述,并至少使用TypeScript v1.7,您可以使用如下的胖箭头来使用它:
$scope.$on('some-event', () => { console.log('here `this` is not undefined'); });
$scope.$watch('foo.bar', (a,b) => { console.log('here too...'); }
$scope.$on('$routeChangeSuccessEvent', () => { console.log('here too...'); });
但是,如果要从同一个类传递对函数的引用,则必须使用.bind(this)
表示法:
$cope.$on('$routeChangeSuccessEvent', this.onRouteChangeStart.bind(this));