【问题标题】:Dynamically accessing properties of knockoutjs observable array动态访问 knockoutjs 可观察数组的属性
【发布时间】:2013-05-02 23:23:21
【问题描述】:

我正在使用以下代码来处理排序功能。它对我有用。但是有什么方法可以使代码变得通用,以便我可以在需要时使用它。

<span class="sorting" data-bind="click: function(){ ui.items.sort(function(a,b){ return a.Username < b.Username ? -1 : 1; }); }">User Name</span>

<span class="sorting" data-bind="click: function(){ ui.items.sort(function(a,b){ return a.Firstname < b.Firstname ? -1 : 1; }); }">
            First Name</span>

<span class="sorting" data-bind="click: function(){ ui.items.sort(function(a,b){ return a.Lastname < b.Lastname ? -1 : 1; }); }">
            Last Name</span>

脚本

ui = new ListUI(config);

ko.applyBindings(ui);


var ListUI = function ListUIF(config) {
   this.items = ko.observableArray([]);
}

var item = function itemF(data) {

        var self = this;

        self.Username = ko.observable(data.Username);
        self.Firstname = ko.observable(data.Firstname);
        self.Lastname = ko.observable(data.Lastname);
}

上面的代码工作正常,但我不想重复排序代码。

<span class="sorting" data-bind="click: function(){ ui.items.sort(function(a,b){   return a.Lastname < b.Lastname ? -1 : 1; }); }">
            Last Name</span>

相反,我想要这样的东西

<span class="sorting" data-bind="click: sortFunction">
            Last Name</span>

var sortFunction = function sortFunctionF(a, b){

   return a.Username < b.Username : -1 : 1;  //How to make this common for other property also like Firstname, Lastname etc.

 }

【问题讨论】:

    标签: javascript jquery asp.net-mvc-4 knockout.js


    【解决方案1】:

    基本上有两种选择:拥有三个独立的函数sortByUsernamesortByFirstnamesortByLastname,或者您可以进行自定义绑定,接收额外的信息并设置排序。

    第二个可能看起来像这样:

    <span class="sorting" data-bind="sortFunction: 'Username'">User Name</span>
    
    <span class="sorting" data-bind="sortFunction: 'Firstname'">
            First Name</span>
    
    <span class="sorting" data-bind="sortFunction: 'Lastname'}">
            Last Name</span>
    

    然后是 sortFunction 的自定义绑定:

    ko.bindingHandlers.sortFunction = {
        update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
            var sortBy = ko.utils.unwrapObservable(valueAccessor());
            var items = viewModel.items;
            $(element).unbind('click.sort').bind('click.sort', function() {
                items.sort(function(a, b) {
                    return a[sortBy]() < b[sortBy]() ? -1 : 1;
                 });
            });
        }
    }
    

    Fiddle

    Joeseph 提到的另一个选项是将属性名称传递给 click 函数,然后该函数将返回一个函数。我不认为这是一个与自定义绑定一样好的选项,但Here's 是一个可以做到这一点的小提琴:

    <span class="sorting" data-bind="click: getSortFunction('Username')">User Name</span>
    
    <span class="sorting" data-bind="click: getSortFunction('Firstname')">
            First Name</span>
    
    <span class="sorting" data-bind="click: getSortFunction('Lastname')}">
            Last Name</span>
    

    然后您的视图模型将更改以添加功能:

    var ListUI = function ListUIF(items) {
        var self = this;
       self.items = ko.observableArray(items);
    
        self.getSortFunction = function(prop) {
            return function() {
                self.items.sort(function(a, b) {
                    return a[prop]() < b[prop]() ? -1 : 1;
                });
            };
        };
    
        return self;
    }
    

    【讨论】:

    • 从技术上讲,您可以将属性名称作为字符串传递给函数,并使用数组语法 (obj[propName]) 引用它,但我会选择自定义绑定。
    • 您建议如何将字符串传递给函数?如果您将绑定设置为 Last Name`,您将在 applyBindings 而不是点击时调用该函数。我想你也可以设置sortFunction 来返回一个函数......
    • 这很难看 :) 你必须像这样内联一个匿名函数(使用 OP 的例子)data-bind="click: function(){sortFunction(a,b,"Firstname");}"
    • 不需要内联,只需返回匿名函数即可(我继续实现了它)。
    • 是的,我看到了。这是一个巧妙的想法。不过,我还是会选择绑定!
    猜你喜欢
    • 2017-06-16
    • 2015-11-30
    • 2011-06-13
    • 1970-01-01
    • 2012-04-20
    • 2017-11-25
    • 2017-04-28
    • 1970-01-01
    • 2015-08-11
    相关资源
    最近更新 更多