簡體   English   中英

使用ViewModel外部的計算數組進行JS淘汰

[英]Knockout JS using computed arrays outside of ViewModel

我想在頁面上顯示項目列表,並能夠通過使用所有位置的下拉列表來動態地重新定位項目。 從下拉列表中選擇一個位置將更改該項目的當前位置,並重新移動列表中所有受影響元素的位置。

我確實有這個概念的可行版本,但這並不理想。 由於某種原因,當我引用我的selectedItems計算數組時(我通過將selectedItem設置為observable來過濾我的項目),返回的項目中包含的位置是該項目的原始位置值,而不是通過設置的位置值下拉菜單/我的重新定位功能。 這有點奇怪,因為'items'observableArray確實包含了更新后的值,而calculatedArray確實返回了正確的項目,只是沒有最新的值。

正常工作的JSfiddle在下面。 但是,它進行了大量的手動計算,並且沒有利用如上所述的計算數組。 問題可能與從ViewModel外部設置Knockout可觀察對象有關。 要查看該問題,請取消注釋“文檔准備好”塊中的兩行,在該行中,我嘗試查找項目的當前位置,並注釋掉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觸發器的使用效果不佳。 讓我們用淘汰賽來完成所有工作。

我將items設置為只是一組沒有分配位置的對象。 orderedItems是一種計算方法, 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> 

我可以想到的一種方法是使用計算出的值來保存頭寸的當前狀態。 當在如下所示的項目上設置新職位時,這將允許您進行改組:

ko.utils.arrayForEach(self.items(), function (x) {
        x.newPosition = ko.computed({
            read: function () {
                return x.position();
            },
            write: function (val) {
                //get the item in the prev position
                var temp = ko.utils.arrayFirst(self.items(), function (y) {
                    return y.position() == val;
                });
                //swap positons here
                if (temp) {
                    temp.position(x.position());
                    x.position(val);
                }
            }
        });
    });

在標記中

<select data-bind="options:positions,value:newPosition"></select>

如此計算得出的“寫入”值...腳本會交換位置值。 我將您的原始綁定留給了orderedItems。 您可以在這里https://jsfiddle.net/p1yhmvcr/2/找到一個工作示例。這里值得注意的一件事是排序並不是真正的物理。 可觀察的數組項仍在數組的原始索引上,並且代碼僅更改位置值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM