Декоратор Ractivejs инициализирован непоследовательно

ссылка: http://jsfiddle.net/ffmqd0zz/

HTML:

<div id='books_container'/>

<script type='ractive/template' id="books">
  {{#books}}
  <div decorator='decoration' id="{{id}}">
      <span> title: {{ title }}</span>
      <span> id: {{ id }}</span>
  </div>
  {{/books}}
</script>

JavaScript:

var MyDecorator = function(node) {
    console.log("init MyDecorator for id: " + $(node).attr('id'));
    return { teardown: function() {}};
};

var books = new Ractive({
    el: '#books_container',
    template: '#books',
    data: {books: [{"id": 1174,"title": "franny and zoey"},
                   {"id": 1175,"title": "moby duck"}]},
    decorators: { decoration: MyDecorator }
  });

console.log("init complete")

books.set('books', [{"id": 1176,"title": "life, the universe and stuff"},
                    {"id": 1177,"title": "yellowbrick road"},
                    {"id": 1178,"title": "grapes of wrath"} ]);

обратите внимание, что инициализация декоратора регистрируется в консоли.

Когда Ractive инициализируется, два начальных элемента в списке «книги» оформлены правильно, как указано в сообщениях console.log. Однако, когда список изменяется с помощью «books.set()», Ractive украшает только третий элемент в списке, а декораторы для книг с идентификаторами 1176 и 1177 не инициализируются.

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

Я делаю это неправильно, или это ошибка? И может кто-нибудь предложить обходной путь, пожалуйста.

заранее спасибо


person Les Nightingill    schedule 30.06.2015    source источник


Ответы (2)


Ractive будет обновлять только то, что меняется. Со списками узлов ({{each}}) для обновлений используются две стратегии:

  1. Явные модификации массива, такие как push или splice (или merge), производят идентичные модификации узлов DOM — это означает, что узлы DOM остаются нетронутыми, если они не изменены, в противном случае удаляются или вставляются.
  2. Установка массива повторно использует узлы DOM, но даже в этом случае только те вещи, которые изменились, будут обновлены со структурой каждого элемента списка.

Так что для декораторов, если у них нет параметров, Ractive не будет их обновлять. Каждый способ изменить это, чтобы добавить параметр в ваш декоратор:

<div decorator='decoration:{{id}}' id="{{id}}">

Теперь декоратор будет удален и повторно инициализирован, если данные, от которых он зависит, изменятся (см. http://jsfiddle.net/ffmqd0zz/2/ ).

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

var MyDecorator = function(node, title) {
    console.log('new decorator', title);
    function tooltip( title ) {
        node.title = title;
    }

    return { 
        teardown: function() {},
        update: function( title ) {
            tooltip(title);
        }
    };
  };

см. http://jsfiddle.net/ffmqd0zz/3/

person martypdx    schedule 30.06.2015
comment
Спасибо, Марти. Ни один из ваших примеров не работал так, как я ожидал. Но они дали мне отличный новый инсайт, из которого я смог добраться туда, куда мне нужно. - person Les Nightingill; 01.07.2015

В качестве обходного пути вы можете извлекать и нажимать элементы массива по одному. Полный пример. Соответствующий код:

books.pop('books');
books.pop('books');

books.push('books', {"id": 1176,"title": "life, the universe and stuff"});
books.push('books', {"id": 1177,"title": "yellowbrick road"});
books.push('books', {"id": 1178,"title": "grapes of wrath"});

Я не уверен, связано ли поведение, которое вы видели, с ошибкой или нет. Как вы сказали, это может быть Ractive, оптимизирующий производительность. Один красноречивый факт из документов Ractive: «Директивы — это просто инструкции для Ractive, они на самом деле не добавляются к элементу в качестве атрибутов».

person Keith    schedule 30.06.2015