问题
I'm trying to use typescript with Durandal. I'm trying to make starter example working with typescript, which works for most methods and classes. However in the Flickr class below I experience a problem in the select method. When this method is called it seems that this is not the Flickr class, but the selected item. Can someone help me figure out what is wrong ? The other methods are working as expected.
Kind regards, Marwijn
///<reference path='../../Scripts/typings/requirejs/require.d.ts'/>
///<reference path='../../Scripts/typings/durandal/durandal.d.ts'/>
///<reference path='../../Scripts/typings/knockout/knockout.d.ts'/>
class Flickr
{
app: App;
http: Http;
displayName = 'Flickr';
images = ko.observableArray([]);
constructor(app: App, http: Http)
{
this.app = app;
this.http = http;
}
public activate() : any
{
//the router's activator calls this function and waits for it to complete before proceding
if (this.images().length > 0)
{
return;
}
return this.http.jsonp('http://api.flickr.com/services/feeds/photos_public.gne', { tags: 'mount ranier', tagmode: 'any', format: 'json' }, 'jsoncallback').then((response)=>
{
this.images(response.items);
});
}
public select(item : any) {
//the app model allows easy display of modal dialogs by passing a view model
//views are usually located by convention, but you an specify it as well with viewUrl
item.viewUrl = 'views/detail';
this.app.showModal(item);
}
public canDeactivate() : any
{
//the router's activator calls this function to see if it can leave the screen
return this.app.showMessage('Are you sure you want to leave this page?', 'Navigate', ['Yes', 'No']);
}
}
define(['durandal/http', 'durandal/app'], function (http, app)
{
return new Flickr(app, http);
} );
which is compiled into the following javascript:
var Flickr = (function () {
function Flickr(app, http) {
this.displayName = 'Flickr';
this.images = ko.observableArray([]);
this.app = app;
this.http = http;
}
Flickr.prototype.activate = function () {
var _this = this;
if(this.images().length > 0) {
return;
}
return this.http.jsonp('http://api.flickr.com/services/feeds/photos_public.gne', {
tags: 'mount ranier',
tagmode: 'any',
format: 'json'
}, 'jsoncallback').then(function (response) {
_this.images(response.items);
});
};
Flickr.prototype.select = function (item) {
item.viewUrl = 'views/detail';
this.app.showModal(item);
};
Flickr.prototype.canDeactivate = function () {
return this.app.showMessage('Are you sure you want to leave this page?', 'Navigate', [
'Yes',
'No'
]);
};
return Flickr;
})();
define([
'durandal/http',
'durandal/app'
], function (http, app) {
return new Flickr(app, http);
});
//@ sourceMappingURL=flickr.js.map
回答1:
To get 'this' to reference the view model you can do the following (assuming the flickr.html view has not been changed):
Change the click binding on the thumbnail a tag from
<a href="#" class="thumbnail" data-bind="click:$parent.select">
to
<a href="#" class="thumbnail" data-bind="click: function (item) { $parent.select(item); }">
Because you are then invoking the select method directly on the $parent object (the view model) the view model will be bound to 'this'.
来源:https://stackoverflow.com/questions/15597620/incorrect-this-in-select