2017-03-17 68 views
1

尝试使用foreach命令列表并将列表项随机洗牌。我创建了一个函数(randomOrder)并将其用于绑定在foreach项目上。 似乎没有任何工作。在Knockout.js中随机化Foreach列表项

HTML:

<ol data-bind="foreach: { data: docs, randomOrder: true} "> 
    <li class="result" data-bind="component: { name: 'physicianreferral.docresult', params: { doc: $data } }"></li> 
</ol> 

JS:

ko.bindingHandlers.randomOrder = { 
     init: function (elem, valueAccessor) { 
      // Build an array of child elements 
      var child = ko.virtualElements.firstChild(elem), 
       childElems = []; 
      while (child) { 
       childElems.push(child); 
       child = ko.virtualElements.nextSibling(child); 
      } 

      // Remove them all, then put them back in a random order 
      ko.virtualElements.emptyNode(elem); 
      while (childElems.length) { 
       var randomIndex = Math.floor(Math.random() * childElems.length), 
        chosenChild = childElems.splice(randomIndex, 1); 
       ko.virtualElements.prepend(elem, chosenChild[0]); 
      } 
     } 
    }; 
    ko.virtualElements.allowedBindings.randomOrder = true; 

回答

2

首先你的绑定是不是foreach一部分,因此必须在顶层被指定:

foreach: docs, randomOrder: true 

但我建议你不要使用这种方法。只要你通过数组随机到foreach

foreach: randomize(docs) 

JS:

function randomize(arr) { 
    var newArray = []; 
    while (arr.length) { 
     var randomIndex = Math.floor(Math.random() * arr.length); 
     newArray.push(arr.splice(randomIndex, 1)[0]); 
    } 
    return newArray; 
}; 
+0

迈克尔,这是真正有用的,先生。我认为我正确实现了你的想法,但由于某种原因我得到这个错误: 错误:Uncaught ReferenceError:无法处理绑定“foreach:function(){return randomize(docs)}”消息:randomize未定义 –

+0

对于'randomize'在绑定中可用,它应该是全局函数('window.randomize = ...')或视图模型。 –

+0

有道理!星期一我会出手。再次感谢迈克尔! –

0

一些问题:首先你要使用自定义在foreach结合内结合。您可以在同一个HTML元素中使用多个绑定,但它们应该用逗号分隔。

<ol data-bind="foreach: { data: docs }, randomOrder: true"> 

定制结合“初始化”的方法具有提供一种方式来访问在其它绑定正在使用的相同元件视图模型的属性的allBindingAccessor。

var array = allBindingsAccessor().foreach.data(); 

随着数组可用,你可以使用任何算法来洗牌。我在片段中添加了Fisher-Yates(又名Knuth)Shuffle,直接从answer中复制。点击“运行代码片段”,看看它每次都在洗牌。

ko.bindingHandlers.randomOrder = { 
 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
 
     var array = allBindingsAccessor().foreach.data(); 
 

 
     var currentIndex = array.length, temporaryValue, randomIndex; 
 

 
     // while there remain elements to shuffle... 
 
     while (0 !== currentIndex) { 
 

 
      // Pick a remaining element... 
 
      randomIndex = Math.floor(Math.random() * currentIndex); 
 
      currentIndex -= 1; 
 

 
      // And swap it with the current element. 
 
      temporaryValue = array[currentIndex]; 
 
      array[currentIndex] = array[randomIndex]; 
 
      array[randomIndex] = temporaryValue; 
 
     } 
 

 
     allBindingsAccessor().foreach.data(array); 
 
    } 
 
}; 
 

 
var ViewModel = function() { 
 
    var self = this; 
 

 
    self.docs = ko.observableArray([1, 2, 3, 4, 5, 6, 7, 8 ,9, 10]); 
 
}; 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 
<ol data-bind="foreach: { data: docs }, randomOrder: true"> 
 
    <li data-bind="text: $data"></li> 
 
</ol>

+0

Rafael,感谢您的帮助,我相信它会起作用!我实现了这一点,但由于某种原因它没有任何影响。没有任何错误。 –