WedX - журнал о программировании и компьютерных науках

Knockout.js: обновить привязки?

когда я добавляю новые элементы в DOM после ko.applyBindings(); был вызван, то нокаут не распознает эти новые элементы. Я могу понять, почему это происходит - они просто не индексируются нокаутом.

Итак, сначала я думал, что это можно решить, просто снова вызвав ko.applyBindings() после добавления моих новых элементов, НО потом я понял, что для каждого вызова ko.applyBindings() соответствующие события запускаются несколько раз. Таким образом, после пятикратного применения привязка click: будет срабатывать пять раз, так что это нежелательное решение;)

Есть ли что-то вроде ko.updateBindings() или что-то еще, чтобы сказать нокауту, ну... обновить привязки элементов?

привет, Крис

26.11.2011

  • Можете ли вы опубликовать код, чтобы показать, что вы делаете? 27.11.2011
  • ну например примерно так: $('body').append('‹a href=# data-bind=click: something›Click me!‹/a›'); 27.11.2011
  • Я не уверен, что этого достаточно, чтобы дать полезный ответ. Я понимаю, что вы пытаетесь сделать, но с более полной картиной вашего кода (почему и когда вы вводите новые элементы DOM) трудно ответить, как лучше всего позаботиться об этом. Возможно, после просмотра вашего текущего решения кто-то может указать способ избежать необходимости вводить новые элементы или найти обходной путь для того, что вы пытаетесь сделать. 27.11.2011
  • Кажется, я нашел его. Просто вызов: ko.applyBindings(viewModel); снова привязывает все функции ко всему DOM. По этой причине каждый обратный вызов вызывается дважды и более после повторного вызова этой функции. Второй параметр для applyBindings() — это узел DOM, с которого начинается применение. По умолчанию это корень DOM. Итак, если вы вручную добавляете пару элементов с атрибутами привязки данных к какому-либо узлу DOM, захватите ссылку на узел DOM с новыми элементами и передайте ее в качестве второго параметра! 27.11.2011
  • Потрясающий! Я забыл о втором параметре для applyBindings(). 27.11.2011
  • И если вы делаете это с компонентами KO, и в этом случае вы не можете указать viewModel в качестве первого параметра функции, просто вызовите ko.applyBindings(null, myDomReference) 27.03.2020

Ответы:


1

Каждый раз, когда вы вызываете ko.applyBindings, вся модель DOM проверяется на наличие привязок. В результате вы получите несколько привязок для каждого элемента, если сделаете это более одного раза. Если вы просто хотите связать новый элемент DOM, вы можете передать этот элемент в качестве параметра функции applyBindings:

ko.applyBindings(viewModelA, document.getElementById("newElement"));

См. этот связанный вопрос:

Можете ли вы вызвать ko.applyBindings для привязки частичного представления?

27.11.2011
  • Да, это решение, которое я тоже придумал :) К сожалению, я не нашел прямой документации по API на Knockoutjs.com, и мне пришлось выполнить обратный инжиниринг объекта ko, чтобы выяснить это -.- 27.11.2011
  • Правда, документации по API нет, но она есть в более «многословной» документации. Посмотрите на полпути вниз по этой странице: knockoutjs.com/documentation/observables.html 28.11.2011
  • Вы уверены, что это ответ? Разве это не применит viewModelA к newElement, как будто newElement является корнем DOM для viewModelA? Я вижу, где это сработает несколько или даже в большинстве случаев, но я также вижу, как это может привести к неожиданным результатам (я думаю). 22.12.2011
  • Я просто подумал, что прокомментирую здесь, поскольку я действительно споткнулся о ловушку. Я загружал дочерние представления с помощью ajax и вставлял их в модель представления, которая была привязана к представлению, чтобы разместить дочерние (частичные) представления в нужном месте на главной странице. Нужно быть очень осторожным, с какими элементами они связаны. Я небрежно вызывал applyBindings для элемента, содержащего частичное представление, что, судя по всему, приводило к перезагрузке частичного представления. Мне пришлось изменить логику, чтобы выбрать дочерние элементы этого элемента или, другими словами, весь частичный вид. 17.11.2012
  • Пока узлы не разделяют часть дерева (например, они братья и сестры), вы можете безопасно вызывать applyBindings на каждом из узлов (фактически, это одна из причин для использования второго аргумента). 09.05.2014

  • 2

    Не зная, чем именно вы занимаетесь, кажется, что вы идете неправильным путем. Ваше представление должно управляться вашей моделью представления. Таким образом, вы не должны напрямую добавлять элементы DOM, к которым затем нужно применить нокаутирующие привязки.

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

    Так, например, для вашего $('body').append('<a href="#" data-bind="click: something">Click me!</a>'); вместо добавления элемента DOM, когда кнопка должна быть видимой, управляйте видимостью кнопки с помощью модели представления.

    Итак, ваша модель представления включает

    var viewModel = { clickMeAvailable: ko.observable(false) }
    

    И ваш HTML включает

    <a href="#" data-bind="click: something, visible: clickMeAvailable">Click me!</a>
    

    Когда состояние приложения изменится, и кнопка «Нажми меня» станет доступной, вы просто viewModel.clickMeAvailable(true).

    Смысл этого, и большая часть нокаута, состоит в том, чтобы отделить бизнес-логику от представления. Таким образом, код, который делает доступным click me, не заботится о том, что click me включает в себя кнопку. Все, что он делает, это обновляет viewModel.clickMeAvailable, когда доступен click me.

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

    Но затем вы решаете что-то изменить, поэтому после того, как форма станет действительной, появится юридическое соглашение, с которым необходимо согласиться перед сохранением. Логика вашей формы не меняется - она ​​по-прежнему устанавливает formValid, когда форма действительна. Вы бы просто изменили то, что происходит при изменении formValid.

    Как указывает Лассомбра в комментариях к этому ответу, бывают случаи, когда лучшим подходом может быть прямое манипулирование DOM — например, сложная динамическая страница, на которой вы хотите увлажнять только части представления по мере необходимости. Но вы отказываетесь от части разделения интересов, которое обеспечивает Knockout, делая это. Будьте внимательны, если вы планируете пойти на этот компромисс.

    22.12.2011
  • Хотя я, безусловно, согласен со всем этим, я думаю, что бывают случаи, когда имеет смысл использовать KnockoutJ таким образом, чтобы в конечном итоге вы получили вложенные модели представлений. Возможно, это больше похоже на ситуацию, с которой столкнулся Кристиан. В этом случае у вас должна быть модель представления, которая специально настроена и привязана к вашему вложенному HTML (предположительно, загруженному через ajax), когда он доступен/загрузился. 27.07.2012
  • Для протокола, я думаю, что это правильный ответ. Элемент управления должен быть связан при объявлении, а не управляться поведением события. Knockout — это одна из тех технологий, где вам нужно сохранять единообразие всего подхода, чтобы свести к минимуму раздражающие ошибки. 17.08.2012
  • Как быть с особо крупными сайтами, где меняется само представление? Должны ли все возможные представления быть упакованы на страницу по умолчанию? Конечно нет. Загрузка представления через ajax при переходе к другим областям сайта, безусловно, является приемлемым действием (лично я использую это в веб-приложении, которое я конвертирую. Исходное приложение — MVC4 и имеет разные представления для разных личных данных управления, которые я использовал). отслеживание (акции, другие финансовые показатели, список задач, список контактов, календарь событий) Поскольку все они используют одну и ту же главную страницу, преобразование их в MVVM/knockout выполняется довольно просто. 17.11.2012
  • Это справедливое решение, нет единственно верного пути. Но если вы собираетесь начать прямое манипулирование DOM, это должно быть обдуманным решением, зная, что вы жертвуете разделением интересов, которое обеспечивает Knockout. Как я сказал в своем ответе, не зная, что именно вы задумали. Я отредактировал, чтобы отразить ваш комментарий. 18.11.2012

  • 3

    Я только что наткнулся на аналогичную проблему. Я попытался добавить новые элементы в контейнер и дать им функцию onclick.

    Сначала попробовал то, что вы сделали, и даже попробовал подход ColinE рекомендуется. Это не было для меня практичным решением, поэтому я попробовал подход SamStephens и нашел его, который отлично работает для меня:

    HTML:

    <div id="workspace" data-bind="foreach:nodeArr, click:addNode">
    <div class="node" data-bind="attr:{id:nodeID},style:{left:nodeX,top:nodeY},text:nodeID, click:$parent.changeColor"></div>
    </div>
    

    JavaScript:

    <script>
    function ViewModel() {
    var self = this;
    var id = 0;
    self.nodeArr = ko.observableArray();
    self.addNode = function (data, event) {
        self.nodeArr.push({
            'nodeID': 'node' + id,
            'nodeX' : (event.offsetX - 25) + 'px',
            'nodeY' : (event.offsetY - 10) + 'px'
        })
        id++;
    }
    self.changeColor = function(data, event){
        event.stopPropagation();
        event.target.style.color = 'green';
        event.target.style.backgroundColor = 'white';
    }
    }
    ko.applyBindings(new ViewModel());
    </script>
    

    Вы можете поиграть с ним в JS Fiddle, который я сделал.

    06.02.2013
  • Что касается меня... Я давно отказался от KnockoutJS, так как он был слишком негибким для моих целей. 06.02.2013
  • @ChristianEngel KO вряд ли является негибким .. некоторые вещи нужно делать так, как KO (мне еще предстоит найти потребность в перепривязке!), Чтобы доставить удовольствие, но Durandal (который использует KO) -› потрясающая гибкость благодаря поддержке представлений - отдельные представления эффективно уменьшают необходимость ручного частичного связывания, поскольку каждое представление может представить либо свою собственную модель, либо совместное использование [части ] модель. Есть несколько вещей, которые мне не нравятся в KO, но это не связано с отсутствием гибкости! Наблюдаемая модель становится очень гибкой после полного использования. 27.05.2013
  • @ChristianEngel Хакерский, но простой способ обработки случайных (внешних) элементов, внедряемых в DOM, состоит в том, чтобы вставить их в привязку управления потоком, например if (в этом посте показано foreach, которое, возможно, чище для начала) а затем включите содержимое после вставки элементов - новое поддерево будет просто привязано соответствующим образом. нет дополнительного руководства applyBindings, а наблюдаемый объект управляет привязкой потока. Дополнительные привязки, такие как withProperties, можно использовать для уточнения свойств в области видимости. 27.05.2013
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

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

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]