【问题标题】:Passing existing model to knockout component binding?将现有模型传递给淘汰组件绑定?
【发布时间】:2017-01-22 02:51:39
【问题描述】:

我刚刚开始探索淘汰组件,因为我们的代码库是在引入组件之前。

一些我第一次阅读时没有理解的东西。

  1. 如何在component 绑定中使用现有的视图模型?
  2. 调用applyBindings时应该绑定什么?

这是我的意思的一个简单例子。

function Customer() {
  this.name = ko.observable();
  ...
  this.orders = ko.observableArray([]);
}
Customer.prototype.addOrder = function(order) {
  this.orders.push(order);
}
...
function Order() {
  this.date = ko.observable();
  ...
}
...
// HERE I want the component binding in the foreach to use the $data
ko.components.register("Customer", {
  viewModel: Customer,
  template: "<strong data-bind='text: name'></strong><ul data-bind='foreach: orders'><li data-bind='component: "Order"'></li></ul>"
});

ko.components.register("Order", {
  viewModel: Order,
  template: "<span data-bind='text: date'></span>"
});
...

<!-- HERE I would like the component binding to use $data too -->
<div data-bind="component: 'Customer'"></div> 

...

var customer  = new Customer(); 
customer.name = "Test";

var order = new Order();
order.data = new Date();
customer.addOrder(order);

ko.applyBindings(customer);

【问题讨论】:

    标签: javascript knockout.js knockout-3.0


    【解决方案1】:

    您可以通过参数(params)将现有模型传递给组件:

    function Customer(params) {
      this.name = ko.observable(params.name);
      this.orders = ko.observableArray(params.orders);
    }
    Customer.prototype.addOrder = function(order) {
      this.orders.push(order);
    }
    function Order(params) {
      this.date = ko.observable(params.date);
    }
    
    ko.components.register("customer", {
      viewModel: Customer,
      template: "<strong data-bind='text: name'></strong><ul data-bind='foreach: orders'><li><order params='date: date'></order></li></ul>"
    });
    
    ko.components.register("order", {
      viewModel: Order,
      template: "<span data-bind='text: date'></span>"
    });
    
    ko.applyBindings({ modelName: "Some Name", orders: [ { date: "01/01/01" } ] });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <customer params="name: modelName, orders: orders"></customer>

    更新:无视图模型组件激增(我喜欢 @Zoltán Tamási 的这个想法):

    function Customer() {
      this.name = ko.observable();
      this.orders = ko.observableArray([]);
    }
    Customer.prototype.addOrder = function(order) {
      this.orders.push(order);
    }
    function Order() {
      this.date = ko.observable();
    }
    ko.components.register("customer", {
      viewModel: function(params) { return params.model; },
      template: "<strong data-bind='text: name'></strong><ul data-bind='foreach: orders'><li><order params='model: $data'></order></li></ul>"
    });
    
    ko.components.register("order", {
      viewModel: function(params) { return params.model; },
      template: "<span data-bind='text: date'></span>"
    });
    
    var customer  = new Customer(); 
    customer.name = "Test";
    
    var order = new Order();
    order.date = new Date(Date.now());
    customer.addOrder(order);
    
    ko.applyBindings({ customer: customer });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <customer params="model: customer"></customer> 

    【讨论】:

    • 我知道参数。但是我不明白为什么我每次都应该创建一个新的 viewmodel 实例,而不是使用 orders 中的实例。这似乎没有意义。 Customer 实例中已经有准备好的 Order 实例。每个逻辑都告诉我应该在绑定时使用它们,否则它也会不同步。
    • 另外,在我们当前的场景中,我们在应用绑定之前手动实例化整个视图模型结构,因此我们具有完全的灵活性,例如加载初始数据等。据我目前所见,使用 @ 987654328@s 与此方法背道而驰,因为每个组件都坚持创建自己的实例或视图模型。
    • 作为补充,我知道components 没有视图模型,我知道我可以使用它们并通过params 传递现有的视图模型。但这闻起来很糟糕。
    • 是的,我明白,虽然我喜欢自定义元素、AMD 风格的模板加载等想法。所以我想利用这些功能,但保留我现有的视图模型类结构。我只需要一种方法来绕过组件的 viewModel 创建并传递我现有的。也许我会选择没有 viewModel 的组件。
    • 我喜欢你对 viewModel-less 组件的想法,并用尖峰更新了答案。
    【解决方案2】:

    最后一个问题:您仍然applyBindings 到应用程序的视图模型。使用组件不会改变这一点。

    组件can receive parameters。这就是您将任何内容传递给他们的视图模型构造函数的方式。

    【讨论】:

      【解决方案3】:

      您正在寻找的解决方案是使用此视图模型工厂注册您的组件:

      ko.components.register("your-element", { 
          template: {...}, 
         { createViewModel: (params, componentInfo) => ko.dataFor(componentInfo.element) };
      };
      

      这将为您提供“通过”绑定,例如:

      <div data-bind="with: SomeModel">
          <your-element></your-element>
      </div>
      

      为您的模板加载的 HTML 中的视图模型将是 SomeModel。

      【讨论】:

        【解决方案4】:

        您是否尝试过使用“共享对象实例”,例如:http://knockoutjs.com/documentation/component-registration.html#specifying-a-viewmodel

        【讨论】:

          猜你喜欢
          • 2017-12-10
          • 2018-04-18
          • 2012-11-18
          • 2013-04-21
          • 1970-01-01
          • 1970-01-01
          • 2014-01-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多