Как использовать knockout.js с моделями просмотра ASP.NET MVC?

129

премия

Прошло некоторое время, и у меня все еще есть пара нерешенных вопросов. Надеюсь, добавив награду, возможно, на эти вопросы будут даны ответы.

  1. Как использовать html-помощники с knockout.js
  2. Почему документ был готов, чтобы он работал (дополнительную информацию см. В разделе «Первое редактирование»)

  3. Как мне сделать что-то подобное, если я использую отображение нокаута с моими моделями представления? Поскольку у меня нет функции из-за маппинга.

    function AppViewModel() {
    
        // ... leave firstName, lastName, and fullName unchanged here ...
    
        this.capitalizeLastName = function() {
    
        var currentVal = this.lastName();        // Read the current value
    
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    
    };
  4. Я хочу использовать плагины, например, я хочу иметь возможность откатывать наблюдаемые, как если бы пользователь отменял запрос, я хочу иметь возможность вернуться к последнему значению. Судя по моим исследованиям, похоже, что люди создают плагины вроде editables.

    Как мне использовать что-то подобное, если я использую отображение? Я действительно не хочу переходить к методу, в котором у меня есть ручное сопоставление в моем представлении, если бы я сопоставлял каждое поле MVC viewMode с полем модели KO, поскольку я хочу как можно меньше встроенного javascript, и это похоже на двойную работу, и это почему мне нравится это отображение.

  5. Я обеспокоен тем, что для облегчения этой работы (с помощью сопоставления) я потеряю много KO-мощности, но, с другой стороны, я обеспокоен тем, что ручное сопоставление будет просто большой работой и приведет к тому, что мои представления будут содержать слишком много информации и может стать труднее поддерживать в будущем (скажем, если я удалю свойство в модели MVC, мне придется переместить его также в модель просмотра KO)


Исходный пост

Я использую asp.net mvc 3, и я изучаю нокаут, так как он выглядит довольно круто, но мне сложно понять, как он работает с asp.net mvc, особенно с моделями просмотра.

Для меня сейчас я делаю что-то вроде этого

 public class CourseVM
    {
        public int CourseId { get; set; }
        [Required(ErrorMessage = "Course name is required")]
        [StringLength(40, ErrorMessage = "Course name cannot be this long.")]
        public string CourseName{ get; set; }


        public List<StudentVm> StudentViewModels { get; set; }

}

У меня был бы Vm с некоторыми основными свойствами, такими как CourseName, и поверх него была бы простая проверка. При необходимости модель Vm может содержать и другие модели представлений.

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

@Html.TextBoxFor(x => x.CourseName)

У меня может быть несколько циклов foreach или что-то еще, чтобы получить данные из коллекции моделей представления учеников.

Затем, когда я отправлял форму, я бы использовал jquery и serialize arrayотправлял его методу действия контроллера, который привязывал бы его обратно к модели просмотра.

С knockout.js все по-другому, так как теперь у вас есть модели просмотра для него, и из всех примеров, которые я видел, они не используют помощники html.

Как вы используете эти две функции MVC с knockout.js?

Я нашел это видео, и оно вкратце (последние несколько минут видео в 18:48) описывает способ использования моделей просмотра, в основном имея встроенный скрипт с моделью просмотра knockout.js, которой присваиваются значения в ViewModel.

Это единственный способ сделать это? Как насчет моего примера с набором моделей просмотра? Должен ли я иметь цикл foreach или что-то в этом роде, чтобы извлечь все значения и назначить их для нокаута?

Что касается хелперов html, то видео о них ничего не говорит.

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


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

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

@model MvcApplication1.Models.Test

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
   <script type="text/javascript">

   $(function()
   {
      var model = @Html.Raw(Json.Encode(Model));


// Activates knockout.js
ko.applyBindings(model);
   });

</script>

</head>
<body>
    <div>
        <p>First name: <strong data-bind="text: FirstName"></strong></p>
        <p>Last name: <strong data-bind="text: LastName"></strong></p>
        @Model.FirstName , @Model.LastName
    </div>
</body>
</html>

Мне пришлось обернуть его вокруг документа jquery, готового заставить его работать.

Я тоже получаю это предупреждение. Не уверен, о чем идет речь.

Warning 1   Conditional compilation is turned off   -> @Html.Raw

Так что у меня есть отправная точка, я думаю, по крайней мере, обновлю, когда я еще немного поиграю и как это работает.

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

Пока не знаю, как справиться с этими частями

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
}

или

function AppViewModel() {
    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };


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

Я смог разобраться с первой проблемой. Не имею ни малейшего понятия о второй проблеме. Тем не менее. У кого-нибудь есть идеи?

 @model MvcApplication1.Models.Test

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
        <title>Index</title>
        <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
       <script type="text/javascript">

       $(function()
       {
        var model = @Html.Raw(Json.Encode(Model));
        var viewModel = ko.mapping.fromJS(model);
        ko.applyBindings(viewModel);

       });

    </script>

    </head>
    <body>
        <div>
            @*grab values from the view model directly*@
            <p>First name: <strong data-bind="text: FirstName"></strong></p>
            <p>Last name: <strong data-bind="text: LastName"></strong></p>

            @*grab values from my second view model that I made*@
            <p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
            <p>Another <strong data-bind="text: Test2.Another"></strong></p>

            @*allow changes to all the values that should be then sync the above values.*@
            <p>First name: <input data-bind="value: FirstName" /></p>
            <p>Last name: <input data-bind="value: LastName" /></p>
            <p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
            <p>Another <input data-bind="value: Test2.Another" /></p>

           @* seeing if I can do it with p tags and see if they all update.*@
            <p data-bind="foreach: Test3">
                <strong data-bind="text: Test3Value"></strong> 
            </p>

     @*took my 3rd view model that is in a collection and output all values as a textbox*@       
    <table>
        <thead><tr>
            <th>Test3</th>
        </tr></thead>
          <tbody data-bind="foreach: Test3">
            <tr>
                <td>    
                    <strong data-bind="text: Test3Value"></strong> 
<input type="text" data-bind="value: Test3Value"/>
                </td>
            </tr>    
        </tbody>
    </table>

контроллер

  public ActionResult Index()
    {
              Test2 test2 = new Test2
        {
            Another = "test",
            SomeOtherValue = "test2"
        };

        Test vm = new Test
        {
            FirstName = "Bob",
            LastName = "N/A",
             Test2 = test2,

        };
        for (int i = 0; i < 10; i++)
        {
            Test3 test3 = new Test3
            {
                Test3Value = i.ToString()
            };

             vm.Test3.Add(test3);
        }

        return View(vm);
    }
chobo2
источник
2
Я только что написал сообщение в блоге, чтобы ответить на другой похожий вопрос: roysvork.wordpress.com/2012/12/09/ ... Возможно, он не полностью ответит на ваш вопрос, но даст вам хорошее представление о том, как все может работать. Я надеюсь, что в недалеком будущем я напишу еще один пост. Не стесняйтесь задавать мне любые вопросы в комментариях к публикации или здесь, если вам нужна дополнительная информация.
за пределами кода

Ответы:

180

Думаю, я обобщил все ваши вопросы, если я что-то пропустил, дайте мне знать ( если бы вы могли обобщить все ваши вопросы в одном месте, было бы неплохо =))

Заметка. ko.editableДобавлена совместимость с плагином

Скачать полный код

Как использовать html-помощники с knockout.js

Это просто:

@Html.TextBoxFor(model => model.CourseId, new { data_bind = "value: CourseId" })

Куда:

  • value: CourseIdуказывает, что вы привязываете valueсвойство элемента inputуправления к CourseIdсвойству из вашей модели и вашей модели сценария

Результат:

<input data-bind="value: CourseId" data-val="true" data-val-number="The field CourseId must be a number." data-val-required="The CourseId field is required." id="CourseId" name="CourseId" type="text" value="12" />

Почему документ был готов, чтобы он работал (дополнительную информацию см. В разделе «Первое редактирование»)

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

Как мне сделать что-то подобное, если я использую отображение нокаута с моими моделями представления? Поскольку у меня нет функции из-за маппинга.

Если я правильно понимаю, вам нужно добавить новый метод в модель KO, ну, это простое объединение моделей

Для получения дополнительной информации в разделе -Картирование из разных источников-

function viewModel() {
    this.addStudent = function () {
        alert("de");
    };
};

$(function () {
    var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
    var mvcModel = ko.mapping.fromJSON(jsonModel);

    var myViewModel = new viewModel();
    var g = ko.mapping.fromJS(myViewModel, mvcModel);

    ko.applyBindings(g);
});

О предупреждении, которое вы получали

Предупреждение 1 Условная компиляция отключена -> @ Html.Raw

Вам нужно использовать кавычки

Совместимость с плагином ko.editable

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

    ko.editable(g);
    ko.applyBindings(g);

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

    this.editMode = function () {
        this.isInEditMode(!this.isInEditMode());
        this.beginEdit();
    };

Затем у меня есть кнопки фиксации и отмены со следующим кодом:

    this.executeCommit = function () {
        this.commit();
        this.isInEditMode(false);
    };
    this.executeRollback = function () {
        if (this.hasChanges()) {
            if (confirm("Are you sure you want to discard the changes?")) {
                this.rollback();
                this.isInEditMode(false);
            }
        }
        else {
            this.rollback();
            this.isInEditMode(false);
        }
    };

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

this.isInEditMode = ko.observable(false);

О вашем вопросе о массиве

У меня может быть несколько циклов foreach или что-то еще, чтобы получить данные из коллекции моделей представления учеников.

Затем, когда я отправлял форму, я бы использовал jquery и сериализовал массив и отправил его методу действия контроллера, который бы связал его обратно с моделью просмотра.

Вы можете сделать то же самое с KO, в следующем примере я создам следующий вывод:

введите описание изображения здесь

В основном здесь у вас есть два списка, созданные с использованием Helpersи привязанные к KO, у них есть dblClickпривязанное событие, которое при запуске удаляет выбранный элемент из текущего списка и добавляет его в другой список, когда вы публикуете Controllerсодержимое каждого список отправляется как данные JSON и повторно прикрепляется к модели сервера

Nuggets:

Внешние скрипты .

Код контроллера

    [HttpGet]
    public ActionResult Index()
    {
        var m = new CourseVM { CourseId = 12, CourseName = ".Net" };

        m.StudentViewModels.Add(new StudentVm { ID = 545, Name = "Name from server", Lastname = "last name from server" });

        return View(m);
    }

    [HttpPost]
    public ActionResult Index(CourseVM model)
    {
        if (!string.IsNullOrWhiteSpace(model.StudentsSerialized))
        {
            model.StudentViewModels = JsonConvert.DeserializeObject<List<StudentVm>>(model.StudentsSerialized);
            model.StudentsSerialized = string.Empty;
        }

        if (!string.IsNullOrWhiteSpace(model.SelectedStudentsSerialized))
        {
            model.SelectedStudents = JsonConvert.DeserializeObject<List<StudentVm>>(model.SelectedStudentsSerialized);
            model.SelectedStudentsSerialized = string.Empty;
        }

        return View(model);
    }

Модель

public class CourseVM
{
    public CourseVM()
    {
        this.StudentViewModels = new List<StudentVm>();
        this.SelectedStudents = new List<StudentVm>();
    }

    public int CourseId { get; set; }

    [Required(ErrorMessage = "Course name is required")]
    [StringLength(100, ErrorMessage = "Course name cannot be this long.")]
    public string CourseName { get; set; }

    public List<StudentVm> StudentViewModels { get; set; }
    public List<StudentVm> SelectedStudents { get; set; }

    public string StudentsSerialized { get; set; }
    public string SelectedStudentsSerialized { get; set; }
}

public class StudentVm
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Lastname { get; set; }
}

Страница CSHTML

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>CourseVM</legend>

        <div>
            <div class="editor-label">
                @Html.LabelFor(model => model.CourseId)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseId, new { data_bind = "enable: isInEditMode, value: CourseId" })
                @Html.ValidationMessageFor(model => model.CourseId)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.CourseName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseName, new { data_bind = "enable: isInEditMode, value: CourseName" })
                @Html.ValidationMessageFor(model => model.CourseName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(model => model.StudentViewModels);
            </div>
            <div class="editor-field">

                @Html.ListBoxFor(
                    model => model.StudentViewModels,
                    new SelectList(this.Model.StudentViewModels, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: StudentViewModels, optionsText: 'Name', value: leftStudentSelected, event: { dblclick: moveFromLeftToRight }"
                    }
                )
                @Html.ListBoxFor(
                    model => model.SelectedStudents,
                    new SelectList(this.Model.SelectedStudents, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: SelectedStudents, optionsText: 'Name', value: rightStudentSelected, event: { dblclick: moveFromRightToLeft }"
                    }
                )
            </div>

            @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
            @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })
            @Html.HiddenFor(model => model.StudentsSerialized, new { data_bind = "value: StudentsSerialized" })
            @Html.HiddenFor(model => model.SelectedStudentsSerialized, new { data_bind = "value: SelectedStudentsSerialized" })
        </div>

        <p>
            <input type="submit" value="Save" data-bind="enable: !isInEditMode()" /> 
            <button data-bind="enable: !isInEditMode(), click: editMode">Edit mode</button><br />
            <div>
                <button data-bind="enable: isInEditMode, click: addStudent">Add Student</button>
                <button data-bind="enable: hasChanges, click: executeCommit">Commit</button>
                <button data-bind="enable: isInEditMode, click: executeRollback">Cancel</button>
            </div>
        </p>
    </fieldset>
}

Сценарии

<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout.mapping-latest.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ko.editables.js")" type="text/javascript"></script>

<script type="text/javascript">
    var g = null;
    function ViewModel() {
        this.addStudent = function () {
            this.StudentViewModels.push(new Student(25, "my name" + new Date(), "my last name"));
            this.serializeLists();
        };
        this.serializeLists = function () {
            this.StudentsSerialized(ko.toJSON(this.StudentViewModels));
            this.SelectedStudentsSerialized(ko.toJSON(this.SelectedStudents));
        };
        this.leftStudentSelected = ko.observable();
        this.rightStudentSelected = ko.observable();
        this.moveFromLeftToRight = function () {
            this.SelectedStudents.push(this.leftStudentSelected());
            this.StudentViewModels.remove(this.leftStudentSelected());
            this.serializeLists();
        };
        this.moveFromRightToLeft = function () {
            this.StudentViewModels.push(this.rightStudentSelected());
            this.SelectedStudents.remove(this.rightStudentSelected());
            this.serializeLists();
        };
        this.isInEditMode = ko.observable(false);
        this.executeCommit = function () {
            this.commit();
            this.isInEditMode(false);
        };
        this.executeRollback = function () {
            if (this.hasChanges()) {
                if (confirm("Are you sure you want to discard the changes?")) {
                    this.rollback();
                    this.isInEditMode(false);
                }
            }
            else {
                this.rollback();
                this.isInEditMode(false);
            }
        };
        this.editMode = function () {
            this.isInEditMode(!this.isInEditMode());
            this.beginEdit();
        };
    }

    function Student(id, name, lastName) {
        this.ID = id;
        this.Name = name;
        this.LastName = lastName;
    }

    $(function () {
        var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
        var mvcModel = ko.mapping.fromJSON(jsonModel);

        var myViewModel = new ViewModel();
        g = ko.mapping.fromJS(myViewModel, mvcModel);

        g.StudentsSerialized(ko.toJSON(g.StudentViewModels));
        g.SelectedStudentsSerialized(ko.toJSON(g.SelectedStudents));

        ko.editable(g);
        ko.applyBindings(g);
    });
</script>

Примечание: я только что добавил эти строки:

        @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
        @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })

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

Jupaol
источник
Хм очень информативно. Из вашего ответа и ответа Пуала я думаю, что почти получил ответы на все свои вопросы, кроме того, как использовать плагины, такие как редактируемые. Надеюсь, кто-нибудь знает, как я могу это использовать.
chobo2 09
1
Я только что добавил совместимость с ko.editablesподключаемым модулем, вы можете проверить обновленный ответ или, если хотите, вы можете загрузить весь проект, чтобы запустить его локально
Jupaol
Я проверю, когда смогу. Многое нужно было изменить, чтобы заставить его работать? Мне интересно, придется ли мне вносить изменения в каждый найденный мной плагин, а затем сохранять свою собственную версию.
chobo2 09
Нет. Вы будете удивлены, это почти что из коробки
Jupaol 09
1
Большое спасибо, я узнал несколько новых стратегий из вашего ответа. Престижность!
sky-dev
23

Вы можете сериализовать свою модель представления ASP.NET MVC в переменную javascript:

@model CourseVM
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));
    // go ahead and use the model javascript variable to bind with ko
</script>

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

Дарин Димитров
источник
1
Да, я просмотрел интерактивный учебник, который есть на сайте, но я действительно никогда не видел ничего общего с asp.net mvc. Я вижу, что у них также есть какой-то плагин сопоставления, но не уверен, как он подходит. В вашем примере, как бы вы связали его с моделью нокаута (в другом скрипте). Я действительно хочу иметь как можно меньше встроенного javascript (не желательно, но я думаю, что это невозможно)
chobo2
2
Какую проблему вы пытаетесь решить? Если вам нужны представления MVC и вы довольны тем, как их использовать, можете придерживаться их. Если вам нужна привязка и обработка данных на стороне клиента, то KO - отличный выбор. Как показано в этом ответе, вы можете сгенерировать свою модель представления KO из своего кода MVC. Он берет виртуальную машину и сериализует ее в json. Затем на клиенте вы можете сопоставить результаты с моделью просмотра javascript. Затем привяжите модель просмотра к представлению, и все готово. Ключевым моментом является то, что MVC и KO не должны быть связаны каким-либо образом, если вы не хотите, чтобы они были. Все зависит от проблемы, которую вы пытаетесь решить.
Джон Папа
1
Это нормально, что вы не видите ничего общего с asp.net mvc. Knockout - это фреймворк на стороне клиента. Он не знает, и его не волнует, какой язык на стороне сервера вы используете. Эти 2 фреймворка должны быть полностью разделены.
Дарин Димитров
@JohnPapa - Мне нравится, как я делаю это сейчас, но мне также нравится узнавать что-то новое (я вижу, что нокаут может быть очень полезным в некоторых ситуациях). Я знаю, что KO - это сценарий на стороне клиента, но я считаю, что они работают вместе. В настоящее время я создаю свои представления, используя модели представлений и помощники HTML. Так что, на мой взгляд, KO нужно работать вместе с этим. Например, скажем, у вас есть диалог редактирования. Как бы вы спроектировали и поместили значения из базы данных в эти поля. Если бы я использовал свой способ, это было бы представление помощников html, у которых есть viewModel. Заполнит модель просмотра, отправит ее через метод действия и будет использовать.
chobo2
1
@ chobo2, knockout - это фреймворк на стороне клиента. Он использует модели представления на клиенте для реализации шаблона MVC на клиенте. Сервер отключен. Вы также можете использовать на нем модели просмотра. Это просто 2 разных места. Если у вас есть сложная логика, которую вы хотите реализовать на клиенте с помощью javascript, нокаут может упростить это. Иначе, честно говоря, вам это не нужно.
Дарин Димитров
2

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

Например:

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

viewModel.capitalizedName = ko.computed(function() {...}, viewModel);

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

Кроме того, подключаемый модуль сопоставления предоставляет возможность постепенно обновлять модель просмотра, а не воссоздавать ее каждый раз, когда вы переходите туда и обратно (используйте дополнительный параметр в fromJS):

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);

И это выполняет инкрементное обновление данных в вашей модели только сопоставленных свойств. Вы можете узнать больше об этом в документации по сопоставлению.

Вы упомянули в комментариях к ответу Дарина пакет FluentJSON . Я автор этого, но его вариант использования более конкретен, чем ko.mapping. Обычно я бы использовал его только в том случае, если ваши модели просмотра односторонние (например, сервер -> клиент), а затем данные отправляются обратно в каком-то другом формате (или не отправляются вообще). Или если ваша модель просмотра javascript должна быть в формате, существенно отличном от вашей модели сервера.

Пол Тынг
источник
Хм, тогда я думаю, что, возможно, FluentJSON не для меня, поскольку мои модели просмотра большую часть времени работают в обе стороны (я обычно отправляю его обратно через json, а затем привязываю его к модели просмотра в параметре метода действия). Вы знаете, как я могу использовать упомянутые плагины как редактируемые? Наконец, теряю ли я какую-либо функциональность, используя отображение и пытаюсь использовать свою модель просмотра, а не не использую ее?
chobo2 05
Я не использовал плагины, поэтому не уверен. Раньше я просто подписывался на каждое изменение и сохранял стек сериализованных состояний модели представления, которые я нажимал при изменении и выдавал при отмене ( см. Этот вопрос ).
Paul Tyng 05
сопоставление не мешает вам выполнять какие-либо функции, вам просто нужно убедиться и соблюдать его соглашения о том, как оно обрабатывает сопоставление с JS и от него, чтобы все это хорошо работало вместе.
Paul Tyng 05
Хорошо, что принятый ответ на вопрос, который вы разместили, - это в основном то, чем будет плагин. Вот что меня смущает, поскольку вы можете видеть, что они создают модель просмотра, а затем используют свою функцию (ko.observableArrayWithUndo ([])). Если я занимаюсь картированием, я не знаю, как это сделать. Единственное, что приходит в голову, - это написать свое собственное отображение (в чем я сомневаюсь, что смогу прямо сейчас), которое отменяет наблюдаемое или отображает каждое свойство, но тогда у меня в основном есть повторяющиеся модели просмотра, одна для сервера и одна для клиента, и я испугался, что станет невозможно поддерживать
chobo2 05
Ах да, извините, я говорил о своем ответе на этот вопрос, извините, надо было связать напрямую.
Paul Tyng 05