保存挖空功能时如何处理原型

时间:2015-03-20 08:04:06

标签: javascript knockout.js

我收到了这个消息。在消息上我有一个原型"toggleLike"。 在保存我的信息之前,喜欢/不喜欢很有效。然后我收到一个错误:

  

“TypeError:this.isLikedByMe不是函数”

引用行this.isLikedByMe(!this.isLikedByMe());(见下文)。

但是将"toggleLike"作为属性(函数)放到对象上会很好。

但为什么原型会导致此错误?

这是我的代码:

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>

1 个答案:

答案 0 :(得分:2)

虽然你的问题不完整,但我会在这里猜测:你在绑定中使用toggleLike,例如

<button data-bind="click: myMessage.toggleLike">Like</button>

问题不是你正在使用原型上定义的函数,或者原型函数调用构造函数中定义的另一个函数 - 一切正常。

问题是您使用错误的toggleLike执行this。在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绑定中。在上面的绑定示例中:

<!-- we assume that $data here is your viewmodel -->
<button data-bind="click: myMessage.toggleLike">Like</button>

Click上真正发生的事情是Knockout从myMessage“借用”toggleLike,并在this设置为$data的情况下执行它 - 您的viewmodel:

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 -->

同样适用。