2013-06-01 96 views
5

我正在尝试使用knockout-es5 plugin来演示如何简化使用显示模块模式的模型。 ViewModel1是原始Knockout模型,它工作正常。 ViewModel2是一个尝试使用knockout-es5插件。遇到几件事使用Knockout-es5揭示模块模式

  • 由于局部变量未被跟踪(例如fullName1),所计算的属性不起作用。我可以使用ko.defineProperty,但首先将它与其他属性分开,其次必须使用this.propertyName。
  • 成员函数所做的更改不会反映出来,可能出于同样的原因(例如doSomething)。再次使用this.propertyName的作品,但RM模式被违反。

JS Fiddle

var NS = NS || {}; 

$(function() { 

    NS.ViewModel1 = function (first, last) { 
     var 
      firstName = ko.observable(first), 
      lastName = ko.observable(last), 
      fullName = ko.computed(function() { 
       return firstName() + " " + lastName(); 
      }), 
      doSomething = function (n) { 
       lastName(lastName() + " " + n); 
      } 
     ; 

     return { 
      firstName: firstName, 
      lastName: lastName, 
      fullName: fullName, 
      doSomething: doSomething 
     }; 
    }; 

    NS.ViewModel2 = function (first, last) { 
     var 
      firstName = first, 
      lastName = last, 
      fullName1 = ko.computed(function() { 
       // Changed values are not reflected 
       return firstName + " " + lastName; 
      }), 
      fullName2 = ko.computed(function() { 
       // Should not work 
       return this.firstName + " " + this.lastName; 
      }), 
      doSomething = function (n) { 
       // Doesn't work 
       lastName += " " + n; 
       // Works 
       // this.lastName += " " + n; 
      } 
     ; 

     var retObj = { 
      firstName: firstName, 
      lastName: lastName, 
      fullName1: fullName1, 
      fullName2: fullName2, 
      doSomething: doSomething 
     }; 

     ko.track(retObj); 
     ko.defineProperty(retObj, 'fullName3', function() { 
      // Changed values are not reflected 
      return firstName + " " + lastName; 
     }); 
     ko.defineProperty(retObj, 'fullName4', function() { 
      // Works 
      return this.firstName + " " + this.lastName; 
     }); 

     return retObj; 
    }; 

    var vm1 = new NS.ViewModel1("John", "Doe"); 
    ko.applyBindings(vm1, document.getElementById("observableSection")); 

    var vm2 = new NS.ViewModel2("Jane", "Doe"); 
    ko.applyBindings(vm2, document.getElementById("withoutObservableSection")); 

    setTimeout(function() { 
     vm1.firstName("John 1"); 
     vm2.firstName = "Jane 1"; 
    }, 2000); 

    setTimeout(function() { 
     vm1.doSomething(2); 
     vm2.doSomething(2); 
    }, 4000); 
}); 

回答

1

我不确定你的问题是什么,但是它不会与你尝试使用的模式一起工作。

我喜欢knockout-es5的想法,但是它暴露的当前API有一些问题,如果您偏离了他们的模式,可能真的让您陷入麻烦。

另一个问题是,如果您将this.property传递给其他视图模型,而其他视图模型的目标是能够订阅observable或更新observable,那么它显然不起作用。你只需传递当前值。在这种情况下,你必须记得要得到你的财产的实际观察值。使用旧的淘汰赛,当您访问该物业时,您知道您正在传递可观察物。

该项目是年轻的,所以希望这些API问题将得到解决。但是现在,它需要开发人员记住太多事情才能做到正确。

+0

感谢您的回答。该项目已经在使用这种模式,所以我希望使用新插件来简化未来的模型。我越注意到它越多,我意识到这个插件被设计成与上面提到的博客文章和许多其他示例中定义模型的方式一起使用。没关系,我只是想确保我没有错过任何明显的事情。有时答案是“不能这样做”是正确的答案。我会在几天后打开它并接受它。 –

2

它没有工作,因为你直接从GitHub联JS。查看更新的小提琴的工作原理:http://jsfiddle.net/tkirda/Wznkm/1/

该原因不起作用,是因为Github表明内容类型是“text/plain”而不是“application/x-javascript”。

Content-Type:text/plain; charset=utf-8 
Access-Control-Allow-Origin:https://render.github.com 

因此浏览器不执行此代码。我想他们这样做是为了让人们停止从GitHub上盗链文件。

更新:在你的情况下,姓氏被更改,添加console.log,你会看到它的新值。

 doSomething = function (n) { 
      // Doesn't work 
      lastName += " " + n; 
      console.log(lastName); 
      // Works 
      // this.lastName += " " + n; 
     } 

但是,它不被模型使用,因为当您将它们分配给retObj时,只传递了值而不传入。因为字符串是值类型。当你使用函数时,它们是引用类型的。所以你只是更新了局部变量,但是你的模型没有绑定到那个变量上。

var retObj = { 
      firstName: firstName, 
      lastName: lastName, 
      fullName1: fullName1, 
      fullName2: fullName2, 
      doSomething: doSomething 
     };         

我希望这是有道理的。

+0

这两个小提琴工作exac至少对我来说是一样的。问题出在定义模型的两种方法之间。 observableSection按预期工作,而没有ObservableSection则没有。这两个部分都应在两次超时之后显示“John 1 Doe 2”。我在本地也有相同的代码,两个lobs在本地服务,我得到相同的行为。 –

+0

检查更新后的答案。 –

+0

感谢您的更新。我明白为什么它不起作用。有没有办法绕过它,或者可能是我不能一起使用这两者,即使用另一种模式或继续使用属性的传统语法。 –

1

虽然我很讨厌用构造函数和破“这个”关键词,透露出模块模式是与ES5 KO插件几乎完全不兼容(您可以使其在一个非常令人费解的和脆弱的方式工作,只在简单的场景)

可跟踪的特性也需要一个主体对象(所以不像你的私人增值经销商),不能被复制(如你再失去新生成的getter)

所以挑两两害相权取其较小者: p(对我来说,这是ES5的语法)