简体   繁体   中英

How to structure Knockout JS for this scenario (Using ASP.NET MVC)

I'm just starting Knockout. On my View I have a list of Cars displayed.

What is the best way to initially populate the JS array for cars and also subsequently, what is the best way to store the list in JS for lookups, adding, removing etc.

As far as I see it, there are a few options for initially populating:

  • A1. Output a JSON string from .NET that my Knockout uses to populate a Car array.
  • A2. Have a data-id="x" attribute on each Car element, which Knockout uses to populate.

And there are a few options for storing the data in knockout:

  • B1. The Viewmodel has an array of indicies (referring to the .NET ids) and an array for each property of the object.
  • B2. The Viewmodel has an array of custom JS objects (cars), which then has properties like id,color, type etc.

Which is the best way to handle these situations. I'm guessing A1 & B2? I'm a bit worried about the lookup on B2 being slow, because it will require a custom iterator to find objectWithID(x)

My suggestion would be A1 and B2. Because of how knockout works the lookups won't be an issue in most cases. Knockout also has several util helpers to assist on such operations, read this post http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html .

I created this fiddle to show you how I would have structured it: http://jsfiddle.net/ts8DW/

<script>
    var carsArrayDataFromServer = [
        {
            name: 'audi', 
            color: 'red'
        },
            {
            name: 'volvo', 
            color: 'blue'
        },
        {
            name: 'toyota', 
            color: 'green'
        }
    ];
    var CarModel = function (data) {
        this.name = data.name;
        this.color = data.color;
    };

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

        self.cars = ko.observableArray([]);

        self.delete = function(item) {
            self.cars.remove(item);
        };

        self.init(carsArray);

    };
    ViewModel.prototype = {
        init: function(data) {
            if (!data) return;
            var self = this;
            ko.utils.arrayForEach(data, function(item) {
                self.cars.push(new CarModel(item));
            });
        }
    };

    ko.applyBindings(new ViewModel(carsArrayDataFromServer), document.getElementById('cars-app'));
</script>

<div id="cars-app">
    <ul data-bind="foreach: cars">
        <li>
            <span data-bind="text: name"></span>
            <a href="#" data-bind="click: $parent.delete">
                Delete
            </a>
        </li>
    </ul>
</div>

The easiest way to deal with lists of complex data from the server is using the Knockout mapping plugin .

Using dynamic data-x HTML attributes defies the purpose of Knockout, which is to populate static HTML (a template) with data. Use Ajax to request your data model from the server instead.

function CarViewModel(data) {
    var self = this, 
        loaded = new Date();

    ko.mapping.fromJS(data, {}, self);

    self.displayName = ko.computed(function () {
        return [data.color, data.year, data.make, data.model].join(" ");
    });
}

function CarListViewModel() {
    var self = this;

    self.cars = ko.observableArray();

    self.load = function () {
        $.get("cars.json")
        .then(function (data) {
            var carMapping = {
                key: function (data) {
                    return ko.utils.unwrapObservable(data.id);
                },
                create: function (options) {
                    return new CarViewModel(options.data);
                }
            };
            ko.mapping.fromJS(data, carMapping, self.cars);
        });
    };
}

ko.applyBindings(new CarListViewModel());

(Note that this example depends on jQuery for the Ajax requests.)

See this fiddle for a demonstration/explanation: http://jsfiddle.net/Tomalak/Pbh6S/

You might also be interested in a similar answer I wrote earlier: dynamic column and rows with knockoutjs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM