javascript - 在 ViewModel 之外使用计算数组来 knockout JS

标签 javascript jquery knockout.js

我想在页面上显示项目列表,并能够通过使用所有位置的下拉列表动态地重新定位项目。从下拉列表中选择一个位置将更改项目的当前位置,并重新移动列表中任何受影响元素的位置。

我确实有这个概念的工作版本,但它并不理想。由于某种原因,当我引用我的 selectedItems 计算数组(我通过设置 selectedItem 可观察来过滤我的项目)时,返回项目中包含的位置是该项目的原始位置值,而不是通过设置的位置值下拉菜单/我的重新定位功能。这有点奇怪,因为“items”observableArray 确实包含更新后的值,而ComputedArray 确实返回正确的项目,只是不包含最新值。

下面是一个工作的 JSfiddle。然而,它进行了大量的手动计算,并且没有利用如上所述的计算数组。该问题可能与从 ViewModel 外部设置 Knockout 可观察量有关。要查看该问题,请取消注释“文档就绪” block 中的 2 行,我在其中尝试查找项目的当前位置,并注释掉我手动查找当前项目的 for 循环。

https://jsfiddle.net/tq1m873m/5/

总的来说,我是 KnockoutJS 和 JS 的新手,请温柔一点:)

$(document).ready(function () {

    $("select[id^='selectName_']").change(function () {

        //Extract the item ID from the select html id attribute
        var curItemIDNum = $(this).attr('id').substring(15);

        var currentPos = 0;

        // myViewModel.selectedItem("item" + curItemIDNum);
        // currentPos = myViewModel.selectedItems()[0].position();  

        // START - really bad code, shield your eyes
        // I can't seem to get the current position via the 2 commented lines above and have to resort to converting the observable array to a regular array and pulling the value that way. Not pretty!
        var itemsJS = ko.toJS(self.items());
        for (var x = 0; x < itemsJS.length; x++) {
            if (("item" + curItemIDNum) == itemsJS[x].name) {
                currentPos = itemsJS[x].position;
                break;
            }
        }
        // END - really bad code

        reposition("item" + curItemIDNum, currentPos, $(this).val());
        refreshDropDowns();
    });

    refreshDropDowns();

});

最佳答案

您之前正在研究这个问题,但我没有为您提供可行的解决方案。今天,我做到了。您使用 jQuery 触发器的效果不会很好。让我们通过 knockout 来完成这一切。

我将 items 创建为一个没有指定位置的对象数组。 orderedItems 是一个计算值,它按顺序遍历 items 并为 position 创建一个可观察值。

position 可观察对象的订阅调用 moveItemTo,它会重新排列项目,并且所有依赖项都会由 Knockout 更新。

$(function() {
  ko.applyBindings(viewModel());
});

function item(name) {
  return {
    name: name
  };
}

var viewModel = function() {
  var self = {};
  self.items = ko.observableArray([
    item('item1'),
    item('item2'),
    item('item4'),
    item('item5'),
    item('item3')
  ]);

  function moveItemTo(item, pos) {
    var oldPos = self.items.indexOf(item),
      newPos = pos - 1,
      items;
    if (oldPos < newPos) {
      items = self.items.slice(oldPos, newPos + 1);
      items.push(items.shift());
      self.items.splice.bind(self.items, oldPos, items.length).apply(self.items, items);
    } else {
      items = self.items.slice(newPos, oldPos + 1);
      items.unshift(items.pop());
      self.items.splice.bind(self.items, newPos, items.length).apply(self.items, items);
    }


  }
  self.orderedItems = ko.computed(function() {
    return ko.utils.arrayMap(self.items(), function(item, index) {
      var pos = ko.observable(index + 1);
      pos.subscribe(moveItemTo.bind(null, item));
      return {
        name: item.name,
        position: pos
      };
    });
  });
  return self;
}; //end of viewmodel
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>Set the order of the item by selecting a new position from the dropdown:
  <ul data-bind="foreach: orderedItems">
    <li>
      <div>	<span data-bind="text: name"></span>	
        <select data-bind="options: $root.orderedItems, optionsValue:'position', value: position"></select>
      </div>
    </li>
  </ul>
</div>ITEMS CONTENTS:
<BR>
<span data-bind="text: JSON.stringify(ko.toJS(items), null, 4)"></span>

关于javascript - 在 ViewModel 之外使用计算数组来 knockout JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33876711/

相关文章:

jquery - CSS:使多个div向下 float ,然后在到达文档末尾时向右浮动

javascript - 当 Knockout observable 未定义或禁用 JS 时显示默认值

javascript - 模板中被调用两次的 Knockout JS `hasFocus`

javascript - 滚动条在 OS X 上的 Chrome 中不显示

javascript - 如何在浏览器中编辑 javascript

javascript - 无法解析Azure函数中的json消息正文

javascript - Bootstrap 日期时间选择器,单击图像时显示对话框

jquery - 在外部单击时隐藏按钮

javascript - foreach 和模板中的 knockout 组件

javascript - JQuery - 将背景位置设置为鼠标移动的位置