【问题标题】:KnockoutJS Assembling updated data from componentsKnockoutJS 从组件中组装更新的数据
【发布时间】:2018-05-06 05:40:13
【问题描述】:

我是 KnockoutJS 的新手。 我有一个以下列方式工作的应用程序:

  1. 加载页面时,会将复杂的数据结构传递给前端
  2. 这个数据结构被分割成更小的块,这些数据块被传递给组件
  3. 用户与组件交互以编辑数据块
  4. 单击按钮后,应将更新的复杂数据结构传递到后端

我在第四步时遇到了麻烦。我一直在阅读文档,但我无法弄清楚我应该如何获取更新的数据。

这是一个 JSFiddle:https://jsfiddle.net/vrggyf45

这里是 sn-p 中的相同代码。有关我尝试过的内容,请参阅问题的底部。

ko.components.register('firstComponent', {
  viewModel: function(params) {
    var self = this;
    self.firstComponentValue = ko.observable(params.firstComponentValue);
  },
  template: '<div><pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre><input data-bind="value: firstComponentValue, valueUpdate: \'afterkeydown\'"></div>'
});

ko.components.register('secondComponent', {
  viewModel: function(params) {
    var self = this;
    self.secondComponentValue = ko.observable(params.secondComponentValue);
  },
  template: '<div><pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre><input data-bind="value: secondComponentValue, valueUpdate: \'afterkeydown\'"></div>'
});


var json = '{"items":[{"componentName":"firstComponent","firstComponentValue":"somevalue"},{"componentName":"secondComponent","secondComponentValue":"someothervalue"}]}';
var data = JSON.parse(json);
var mainVM = {};
mainVM.items = ko.observableArray(
  ko.utils.arrayMap(data.items,
    function(item) {
      return ko.observable(item);
    }));

ko.applyBindings(mainVM);

$('input[type=button]').click(function() {
  var updatedData = ko.dataFor(document.getElementById('main'));
  //get updated json somehow?
  console.log(data);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="main">
  <pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>
  <div data-bind="foreach: {data: items, as: 'item'}">
    <hr>
    <div data-bind="component: {name:componentName, params: item}">
    </div>
  </div>
  <hr>
  <input type="button" value="post data">
</div>

如果我有一个单一的视图模型,我可以使用ko.dataFor($("#rootElement")) 并将其发送到后端。但是我打算使用组件,它们有自己的视图模型,它们没有连接到根视图模型。我可以用 jQuery 找到它们并使用ko.dataFor,但它对我来说似乎是个大问题。 我也可以定义所有的视图模型,包括主视图模型中的组件,但它使组件有点无用。

我还尝试更改组件视图模型的构造函数,以便它们改变输入数据并使用可观察对象覆盖传入的值,但这对我来说似乎也是一种 hack。

有没有像ko.components 这样的功能或者可以给我所有活的视图模型的东西?

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    您可以将可观察对象传递给组件,以便它们的编辑立即反映在父对象中。 ko.mapping 可以方便地将普通的 JS 对象转换为可观察对象。然后,当您想要返回数据时,ko.toJS() 它。

    ko.components.register('firstComponent', {
      viewModel: function(params) {
        var self = this;
        self.firstComponentValue = params.firstComponentValue;
      },
      template: '<div><pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre><input data-bind="value: firstComponentValue, valueUpdate: \'afterkeydown\'"></div>'
    });
    
    ko.components.register('secondComponent', {
      viewModel: function(params) {
        var self = this;
        self.secondComponentValue = params.secondComponentValue;
      },
      template: '<div><pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre><input data-bind="value: secondComponentValue, valueUpdate: \'afterkeydown\'"></div>'
    });
    
    
    var json = '{"items":[{"componentName":"firstComponent","firstComponentValue":"somevalue"},{"componentName":"secondComponent","secondComponentValue":"someothervalue"}]}';
    var data = JSON.parse(json);
    var mainVM = {};
    mainVM.items = ko.mapping.fromJS(data.items);
    
    ko.applyBindings(mainVM);
    
    $('input[type=button]').click(function() {
      var updatedData = ko.toJS(ko.dataFor(document.getElementById('main')));
      //Or, more simply: updatedData = ko.toJS(mainVM);
      console.log(updatedData);
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div id="main">
      <pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>
      <div data-bind="foreach: {data: items, as: 'item'}">
        <hr>
        <div data-bind="component: {name:componentName, params: item}">
        </div>
      </div>
      <hr>
      <input type="button" value="post data">
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-16
      • 2019-02-17
      • 2018-07-20
      • 2017-04-28
      • 1970-01-01
      • 2012-04-10
      相关资源
      最近更新 更多