我得到了这个对象消息。在消息上我有一个原型(prototype)“toggleLike”
。
在我保存消息之前,喜欢/不喜欢的效果非常好。然后我得到一个错误:
"TypeError: this.isLikedByMe is not a function"
引用行 this.isLikedByMe(!this.isLikedByMe());
(见下文)。
但是,将 "toggleLike"
作为对象的属性(函数)效果很好。
但是为什么原型(prototype)会导致这个错误呢?
这是我的代码:
Message = function (data) {
var self = this;
self.messageID = data.messageID;
self.messageText = ko.observable(data.messageText);
self.isLikedByMe = ko.observable(data.isLikedByMe || false);
// //this works
// self.toggleLike = function(){
// self.isLikedByMe(!self.isLikedByMe());
// };
return self;
};
Message.prototype.toggleLike = function () {
this.isLikedByMe(!this.isLikedByMe());
};
viewModel = function () {
var self = this;
self.myMessage = ko.observable(
new Message({
messageID: -1,
messageText: 'This is an example'
})
);
self.likeThisMessage = function (data) {
data.toggleLike();
// some more code
};
self.sendMessage = function (data) {
var newmsg = new Message({
ID: -1,
messageText: self.myMessageText(),
});
self.saveMessage(newmsg);
};
self.saveMessage = function (msg) {
if (msg.ID == -1) {
//ajax insert
return $.ajax({
type: "POST",
url: serviceRoot + "InsertMessageItem",
beforeSend: serviceFramework.setModuleHeaders,
data: msg,
cache: false
});
// handle returndata and update msg.ID to value from db.
}
else {
// update ...
}
};
}; // viewModel ends
HTML:
<ul data-bind="with: myMessage">
<li>
<span data-bind="text:messageText"><br/>
<a href="#self" data-bind="visible: !toggleLike(), click:$root.likeThisMessage">Like</a>
<a href="#self" data-bind="visible: toggleLike(),click:$root.likeThisMessage">Unlike</a>
</li>
</ul>
最佳答案
虽然你的问题不完整,但我在这里冒险猜测:你在绑定(bind)中使用 toggleLike
,例如
<button data-bind="click: myMessage.toggleLike">Like</button>
问题不在于您正在使用原型(prototype)上定义的函数,也不在于原型(prototype)函数调用构造函数中定义的另一个函数 - 所有这些都工作正常。
问题是您正在使用错误的 this
执行 toggleLike
。在 Javascript 中,您可以从对象“借用”函数并在完全不同的上下文中执行它们,这意味着它们内部有不同的 this
:
var Mary = function Mary() {
this.name = 'Mary';
this.sayName = function sayName() {
console.log('My name is ' + this.name);
};
};
var Sue = function Sue() {
this.name = 'Sue';
};
var mary = new Mary(),
sue = new Sue();
mary.sayName.call(sue);
// executes Marys `sayName` with `this` set to `sue`
在 Knockout 中,这种情况可能会意外发生,通常发生在 click
绑定(bind)中。在上面的绑定(bind)示例中:
<!-- we assume that $data here is your viewmodel -->
<button data-bind="click: myMessage.toggleLike">Like</button>
点击时真正发生的事情是 Knockout 从 myMessage 中“借用”toggleLike
,并在将 this
设置为 $data
的情况下执行它 — 您的 View 模型:
Message.prototype.toggleLike = function () {
// `this` is now your viewmodel, which does not have `isLikedByMe`
this.isLikedByMe(!this.isLikedByMe());
};
使用bind
避免这种情况:
<button data-bind="click: myMessage.toggleLike.bind(myMessage)">Like</button>
另一种方法是确保 $data
是您尝试调用函数的对象:
<!-- ko with: myMessage -->
<button data-bind="click: toggleLike">Like</button>
<!-- /ko -->
效果也一样。
关于javascript - 保存 knockout 函数时如何处理原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29161978/