javascript - 保存 knockout 函数时如何处理原型(prototype)

标签 javascript knockout.js

我得到了这个对象消息。在消息上我有一个原型(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/

相关文章:

javascript - 我无法在不显示错误的情况下更改输入单词的大写。我用过 toLowerCase()

javascript - 日期选择器未启动

javascript - 如果值未更改,则触发 onchange 事件

javascript - knockout ko.mappings.fromJS 不工作

knockout.js - Hot Towel SPA - 触发浏览器在表单提交时保存登录详细信息

javascript - Knockout JS,如何将$符号添加到observable

JavaScript + RegEx 复杂化——搜索不包含子字符串的字符串

javascript - 使用带有非常简单脚本的 Node 发送后无法设置 header

javascript - knockout 数据绑定(bind)未通过选择绑定(bind)更新自定义事件

visual-studio - knockout 区域突出显示 - Visual Studio 2013