Я чрезмерно использую плагин отображения Knockout, всегда используя его, чтобы сделать мою модель представления? - PullRequest
56 голосов
/ 20 сентября 2011

Я все еще изучаю правильное использование Knockout, и я быстро избавляюсь от необходимости набирать ko.observable при настройке моей модели представления и вместо этого просто определить литерал объекта и передать его через подключаемый модуль сопоставления с чем-то вроде

var viewModel = ko.mapping.fromJS(data);

или, по крайней мере, что-то вроде вставки всех моих данных в атрибут в viewModel, например, так:

var viewModel = { 
    ... events etc ... , 
    "data": ko.mapping.fromJS(data)
}

Если честно, главная причина, по которой яэто делается для того, чтобы обойти необходимость повторного ввода ko.observable и ko.observableArray.Я просто пытаюсь выяснить, является ли это хорошим подходом и есть ли недостатки в отбрасывании конкретной декларации var x = ko.observable() вместе.Кроме того, я делаю все это под нагрузкой, а не в ответ на какой-либо вызов ajax и т. Д., Из чего я могу сказать, для чего и был разработан плагин сопоставления.

В вашей работе с нокаутом выпо-прежнему объявляйте наблюдаемые вручную, один за другим, или вы использовали метод mapping.fromJS, который я использую?Есть ли какие-то определенные недостатки использования плагина картирования так часто, как это?

Редактировать:

Конкретный пример

В этой статье Стив настраивает свою модель представления, выполняя

var initialData = [ { ... } , { ... } ]; // json from the serializer
var viewModel = {
    gifts : ko.observableArray(initialData)
};

Обычно,Я бы просто использовал ko.mapping.fromJS для этой ситуации, в частности, чтобы убедиться, что объекты в массиве также превращаются в наблюдаемые.Глядя на то, что он сделал, мой подход кажется излишним и добавляет немного ненужных накладных расходов.

Ответы [ 4 ]

58 голосов
/ 12 апреля 2012

После небольшого использования Knockout я заметил, что плагин для отображения имеет несколько дополнительных опций, которые дают вам гораздо более детальный контроль над процессом отображения.

Тип управления и количество сгенерированных свойств

Есть несколько способов сделать это, и я расскажу о некоторых, но в итоге вы получите более легкий результат из плагина картирования, потому что все не наблюдается.

По сути, вы оставляете все, что, по вашему мнению, изменится, как обычное свойство и делаете наблюдаемые только из тех конкретных предметов, которые вы хотите наблюдать.

Сделать mapping опустить определенные свойства

Вы можете сделать так, чтобы плагин сопоставления полностью исключал свойства из конечного результата, указав такие вещи, как ignore или include. Оба они выполняют одно и то же, только в противоположных направлениях.

Примечание: образцы взяты из документации подключаемого модуля knockout.js , комментарии, добавленные мной

Аргумент подключаемого модуля: include

Следующий фрагмент опускает все свойства из исходного объекта, кроме тех, которые передаются через аргумент include.

// specify the specific properties to include as observables in the end result 
var mapping = {
    // only include these two properties
    'include': ["propertyToInclude", "alsoIncludeThis"]
}

// viewModel will now only contain the two properties listed above, 
//    and they will be observable
var viewModel = ko.mapping.fromJS(data, mapping);

Плагин Mapping Argument: ignore

Если вы хотите только опустить определенные свойства из исходного объекта, используйте аргумент ignore, как показано ниже. Он создаст наблюдаемые из всех свойств исходного объекта, кроме указанных свойств.

// specify the specific properties to omit from the result, 
//    all others will be made observable
var mapping = {
    // only ignore these two properties
    'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}

// viewModel will now omit the two properties listed above, 
//    everything else will be included and they will be an observable
var viewModel = ko.mapping.fromJS(data, mapping);

Контроль, какие свойства являются или не являются наблюдаемыми

Если вам нужно включить свойства, но вы не думаете, что их нужно будет сделать наблюдаемыми (по какой-либо причине), подключаемый модуль сопоставления может кое-что помочь.

Аргумент подключаемого модуля: copy

Если вы хотите, чтобы подключаемый модуль просто копировал простые свойства и не делал их видимыми, используйте этот аргумент, как показано ниже.

// tell the mapping plugin to handle all other properties normally, 
//    but to simply copy this property instead of making it observable
var mapping = {
    'copy': ["propertyToCopy"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

Получите полный контроль над процессом отображения

Если вы хотите иметь 100% контроль над тем, что создается в процессе отображения, , включая возможность помещать замыкания и подписки в ваши объекты , тогда вы хотите использовать опцию «создать».

простой результат с вычисленными свойствами

Вот пример, в котором я отображал данные из вызова ajax на объект со свойством results. Я не хотел ничего наблюдаемого и просто хотел сгенерированное свойство, которое будет сделано из других простых свойств объекта. Возможно, не самый убедительный пример, но он демонстрирует функциональность.

var searchMappingConfig = {
    // specific configuration for mapping the results property
    "results": {
                    // specific function to use to create the items in the results array
        "create": function (options) {
            // return a new function so we can have the proper scope/value for "this", below
            return new function () {

                // instead of mapping like we normally would: ko.mapping.fromJS(options.data, {}, this);
                // map via extend, this will just copy the properties from the returned json element to "this"
                // we'll do this for a more light weight vm since every last property will just be a plain old property instead of observable
                $.extend(this, options.data);

                // all this to add a vehicle title to each item
                this.vehicleTitle = this.Year + "<br />" + this.Make + " " + this.Model;
                }, this);
            };
        }
    }
}

подписки и закрытия и сопоставления, о, мой

Другая ситуация, если вам нужны закрытия и подписки в вашем результате. Этот пример слишком длинный, чтобы включать его целиком, но для иерархии марок и моделей автомобилей. Я хотел, чтобы все модели (дочерние) для данного производителя (родительского) были отключены, если модель была отключена, и я хотел, чтобы это было сделано с помощью подписки.

// here we are specifying the way that items in the make array are created, 
//    since makes has a child array (Models), we will specify the way that 
//    items are created for that as well
var makesModelsMappingConfig = {
   // function that has the configuration for creating makes
   "create": function (options) {
      // return a new function so we can have the proper 
      //    scope/value for "this", below
      return new function () {

         // Note: we have a parent / child relationship here, makes have models. In the 
         //    UI we are selecting makes and then using that to allow the user to select 
         //    models. Because of this, there is going to be some special logic in here 
         //    so that all the child models under a given make, will automatically 
         //    unselect if the user unselects the parent make.

         // make the selected property a private variable so it can be closure'd over
         var makeIsSelected = ko.protectedComputed(false);

         // expose our property so we can bind in the UI
         this.isSelected = makeIsSelected;

         // ... misc other properties and events ...

         // now that we've described/configured how to create the makes, 
         //    describe/configure how to create the models under the makes
         ko.mapping.fromJS(options.data, {
            // specific configuration for the "Models" property                  
            "Models": {
               // function that has the configuration for creating items 
               //    under the Models property
               "create": function (model) {

                  // we'll create the isSelected as a local variable so 
                  //    that we can flip it in the subscription below, 
                  //    otherwise we wouldnt have access to flip it
                  var isSelected = ko.protectedComputed(false);

                  // subscribe to the parents "IsSelected" property so 
                  //    the models can select/unselect themselves
                  parentIsSelected.current.subscribe(function (value) {
                     // set the protected computed to the same 
                     //    value as its parent, note that this 
                     //    is just protected, not the actual value
                     isSelected(value);
                  });


                  // this object literal is what makes up each item 
                  //    in the Models observable array 
                  return {
                     // here we're returning our local variable so 
                     //    we can easily modify it in our subscription
                     "isSelected": isSelected,

                     // ... misc properties to expose 
                     //     under the item in the Model array ...

                  };
               }
            }
         }, this);
      };
   }
};

В целом, я обнаружил, что вам редко требуется 100% объекта, который вы передаете плагину, и вам редко нужно 100% его для наблюдения. Раскройте с настройками конфигурации сопоставления и создавать всевозможные сложные и простые объекты. Идея состоит в том, чтобы получить только все, что вам нужно, ничего более или менее.

22 голосов
/ 22 сентября 2011

Мое предложение вам было бы таким же, как и на другой вопрос, на который я только что ответил https://stackoverflow.com/questions/7499133/mapping-deeply-hierarchical-objects-to-custom-classes-using-knockout-mapping-plug.

Ваше обоснование использования подключаемого модуля сопоставления является обоснованным и тем, которое я использую. Зачем вводить больше кода, чем нужно?

В своем опыте с нокаутом (все 4 месяца) я обнаружил, что чем меньше я делаю вручную и позволяю рутинам нокаута делать свое дело, тем лучше кажется, что мои приложения работают. Мое предложение - сначала попробуйте самый простой подход. Если он не отвечает вашим потребностям, посмотрите, как простой подход делает свою «вещь», и определите, что нужно изменить, чтобы удовлетворить ваши потребности.

4 голосов
/ 22 июня 2012

Аллен, мой недавний опыт обучения Knockout.js был похож на ваш.Мы работаем с глубоким иерархическим графом объектов с сервера, и я определил явные инстанцируемые функции модели представления, которые сохраняют его базовую структуру.

Я начал с явного определения каждого свойства как наблюдаемого в соответствующей модели представления,но это быстро вышло из-под контроля.Кроме того, основной причиной перехода на плагин сопоставления было то, что нам приходилось делать частые записи Ajax-графика обратно на сервер, где он сливался с постоянной версией, а затем проверялся на сервере таким образом, чтобы многочисленные свойства моглиизменение и коллекции будут изменены, и новый экземпляр будет возвращен как результат Ajax, где он должен быть повторно объединен с клиентским представлением.Это стало очень сложно, и плагин для сопоставления очень помог, позволив спецификацию идентификаторов для разрешения добавления / удаления / обновления и переназначения обновленного графика в исходный.

Это также помогло в создании исходного графика черезиспользование опции «создать» для моделей подвидов.В каждом конструкторе модели представления я получаю ссылку на модель родительского представления плюс данные, с помощью которых строится модель дочернего представления, а затем создаю дополнительные параметры сопоставления для создания внуков из переданных дочерних данных.

Единственное(Небольшой) недостаток, который я недавно обнаружил, как подробно описано в этом вопросе , заключается в том, что при выполнении ko.mapping.toJSON он не привязывается к каким-либо переопределениям toJSON, которые вы, возможно, определили в прототипах моделей представлений вЧтобы исключить свойства из сериализации.Я смог обойти это, указав параметры игнорирования в отображении, как рекомендовано Райаном Нимейером в этом посте.

Итак, в общем, я определенно буду придерживаться подключаемого модуля отображения.Правила Knockout.js.

1 голос
/ 24 апреля 2012

Более простым, но полным справки дополнением может быть knockout-data-projection

В настоящее время он не обрабатывает js для сопоставлений viewmodel, но довольно хорошо обрабатывает отображение модели в сопоставления JS.

...