声明为对象文字与函数的淘汰赛视图模型之间的区别

IT技术 javascript knockout.js
2021-01-16 20:44:25

在淘汰赛 js 中,我看到视图模型声明为:

var viewModel = {
    firstname: ko.observable("Bob")
};

ko.applyBindings(viewModel );

或者:

var viewModel = function() {
    this.firstname= ko.observable("Bob");
};

ko.applyBindings(new viewModel ());

如果有的话,两者有什么区别?

我确实在knockoutjs google group 上找到了这个讨论,但它并没有真正给我一个满意的答案。

如果我想用一些数据初始化模型,我可以看到一个原因,例如:

var viewModel = function(person) {
    this.firstname= ko.observable(person.firstname);
};

var person = ... ;
ko.applyBindings(new viewModel(person));

但如果我不这样做,我选择哪种风格有关系吗?

2个回答

使用函数定义视图模型有几个优点。

主要优点是您可以立即访问this等于正在创建的实例的值这意味着您可以:

var ViewModel = function(first, last) {
  this.first = ko.observable(first);
  this.last = ko.observable(last);
  this.full = ko.computed(function() {
     return this.first() + " " + this.last();
  }, this);
};

因此,this即使从不同的范围调用,您计算出的 observable 也可以绑定到 的适当值

使用对象文字,您必须执行以下操作:

var viewModel = {
   first: ko.observable("Bob"),
   last: ko.observable("Smith"),
};

viewModel.full = ko.computed(function() {
   return this.first() + " " + this.last();
}, viewModel);

在这种情况下,您可以viewModel直接在计算出的 observable 中使用,但它会立即进行评估(默认情况下),因此您无法在对象字面量中定义它,因为viewModel直到对象字面量关闭后才定义。许多人不喜欢视图模型的创建没有封装到一个调用中。

另一种可用于确保this始终合适的模式是将函数中的变量设置为等于合适的值this并改为使用它。这会是这样的:

var ViewModel = function() {
    var self = this;
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         self.items.remove(item);
    }
};

现在,如果您在单个项目的范围内并调用$root.removeItem, 的值this实际上将是在该级别绑定的数据(即项目)。通过在这种情况下使用 self,您可以确保将其从整体视图模型中删除。

另一种选择是使用bind,现代浏览器支持它,如果不支持,则由 KO 添加。在这种情况下,它看起来像:

var ViewModel = function() {
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         this.items.remove(item);
    }.bind(this);
};

关于这个主题还有很多可以说的,你可以探索许多模式(比如module模式和揭示module模式),但基本上使用函数可以让你更灵活地控制对象的创建方式以及引用的能力实例私有的变量。

@JohnPapa - 刚刚在淘汰赛中观看了您的 PluralSight 视频(刚刚超过一半 - 巧合的是,刚刚观看了关于对象文字与函数的部分)。做得非常好,帮助减少了便士。仅凭这一点就值得订阅一个月。
2021-03-15 20:44:25
不应该是 self.items = ko.observableArray(); 在你的第二个例子中?你用过这个,对吗?
2021-03-23 20:44:25
@JackNova 在构造函数中selfthis是相同的,所以两者都是等价的。在 removeItem 函数中,self确实变得更有用,因为this在子项的上下文中执行时不再是当前实例。
2021-03-24 20:44:25
很好的答案。我经常为像视图模型这样的复杂对象使用一个函数(使用揭示module模式)。但是对于简单的模型,我使用了一个函数,这样我就可以在一个地方处理所有事情。
2021-04-01 20:44:25
@Kev - 谢谢。很高兴你从中获得了value。有些人不会关心那个module,因为它不是一个真正的淘汰赛概念,更多的是 JavaScript 模式。但是随着 Knockout 的深入,我发现这些概念确实帮助我创建了更清晰、更稳定的代码。不管怎样,很高兴你喜欢它:)
2021-04-02 20:44:25

我使用了不同的方法,虽然相似:

var viewModel = (function () {
  var obj = {};
  obj.myVariable = ko.observable();
  obj.myComputed = ko.computed(function () { return "hello" + obj.myVariable() });

  ko.applyBindings(obj);
  return obj;
})();

几个原因:

  1. 不使用this,在ko.computeds 等中使用时会造成混淆
  2. 我的 viewModel 是一个单例,我不需要创建多个实例(即new viewModel()
如果没记错的话,这是揭示module模式。很好的答案,但问题不是关于这种模式。
2021-03-21 20:44:25
@paul:很抱歉要求旧线程。你说过,My viewModel is a singleton, I don't need to create multiple instances (i.e. new viewModel()) 但不清楚你想说什么,你I don't need to create multiple instances 能不能用更多的用法来理解你的方法的优点。谢谢
2021-03-25 20:44:25
IMO,您将 ViewModel 声明为 a 的原因之一function是因为您将多次执行它。但是,在我的示例中,它是一个立即调用的匿名函数,因此不会多次创建。它与上面示例中的 Object Literal 非常相似,但为您提供了更多隔离
2021-04-01 20:44:25