0

Итак, я создаю приложение на основе Backbone.js, используя шаблоны для рендеринга некоторых объектов.Решение для шаблонов Javascript, которое позволяет использовать после инъецируемых объектов после рендеринга?

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

Чтобы проиллюстрировать, у меня есть список объектов, скажем, Задачи. У меня есть модель, которая может быть упрощенной как таковые:

{{#each tasks.models as |task|}} 
<div> 
{{task.name}} 
</div> 
{{/each}} 

Теперь, мне нужно будет использовать «задачу» объект динамически, после того, как рендеринг закончен. Например, сделайте примерно следующее:

<div> 
{{task.name}} - <button onClick="task.setComplete()" /> 
</div> 

Конечно, этот способ не работает; и не делают ничего подобного {{task}}.setComplete(), так как {{task}} преобразуется в строку при рендеринге.

Есть ли способ сделать это?

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

Любая идея? Может быть, существуют библиотеки шаблонов, которые позволяли бы создавать непосредственно объекты DOM, которые я мог бы добавить в мой документ?

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

+2

Вы используете Магистраль, так почему бы вам не использовать атрибут onClick, а не обрабатывать событие click через «события»? Попытка сочетать функциональный код с вашими шаблонами отображения обычно приводит к запутанному беспорядку путаницы. –

+0

Спасибо за вход! Если в шаблоне нет ссылки на ссылку, это то, что я буду делать. Однако мне нужно будет сопоставить идентификаторы объектов из шаблона с идентификаторами в моем базовом коде на нескольких уровнях, поэтому, похоже, более сложный код будет иметь прямую ссылку в шаблоне. –

+0

Вы можете подбрасывать 'id' в атрибутах данных следующим образом: http://stackoverflow.com/a/7825773/479863 –

ответ

1

Этого вопрос помечен так что вы должны использовать обычную систему обработки вида события Магистральной, вместо того чтобы onclick обработчиков , Вы упомянули tasks.models, поэтому предположительно tasks - это коллекция.

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

{{#each tasks}} 
    <div> 
     {{name}} - <button data-id="{{id}}" type="button">Completed</button> 
    </div> 
{{/each}} 

, а затем ваш взгляд будет создана так:

Backbone.View.extend({ 
    events: { 
     'click button': 'completed' 
    }, 
    render: function() { 
     var t = Handlebars.compile($('#whatever-the-template-is').html()); 
     this.$el.append(t({ 
      tasks: this.collection.toJSON() 
     })); 
     return this; 
    }, 
    completed: function(ev) { 
     var id = $(ev.currentTarget).data('id'); 
     var m = this.collection.get(id); 
     // Do whatever needs to be done to the model `m`... 
    } 
}); 

Демо:https://jsfiddle.net/ambiguous/z7go5ubj/

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

Если детали вашей модели более сложны, вы можете иметь один вид для коллекции и подсмотров для каждой модели.В этом случае ваши шаблоны для каждой модели будут выглядеть так:

<div> 
    {{name}} - <button type="button">Completed</button> 
</div> 

Больше не требуется атрибут данных. Вы бы новый в-модели вид что-то вроде этого:

var VM = Backbone.View.extend({ 
    events: { 
     'click button': 'completed' 
    }, 
    render: function() { 
     var t = Handlebars.compile($('#whatever-the-template-is').html()); 
     this.$el.append(t(this.model.toJSON())); 
     return this; 
    }, 
    completed: function() { 
     console.log('completed: ', this.model.toJSON()); 
    } 
}); 

и цикл будет двигаться к просмотру коллекции:

var VC = Backbone.View.extend({ 
    render: function() { 
     this.collection.each(function(m) { 
      var v = new VM({ model: m }); 
      this.$el.append(v.render().el); 
     }, this); 
     return this; 
    } 
}); 

Демо:https://jsfiddle.net/ambiguous/5h5gwhep/

Конечно, в в реальной жизни ваш VC будет отслеживать его VM s, так что VC#remove мог позвонить remove на все его детище VM s.

1

Мой ответ только намек, я пытался держаться поближе к вопросу. Обратитесь к этому ответу за лучшим решением: https://stackoverflow.com/a/32493586/1636522.

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

var tasks = []; 
 
var source = $('#source').html(); 
 
var template = Handlebars.compile(source); 
 
tasks[0] = { id: 42, label: 'coffee', description: 'Have a cup of coffee.' }; 
 
tasks[1] = { id: 13, label: 'help', description: 'Connect to StackOverflow.' }; 
 
tasks[2] = { id: 40, label: 'smile', description: 'Make μ smile.' }; 
 
$('#placeholder').html(template({ tasks: tasks })); 
 

 
function onClick (id) { 
 
    var task, i = 0, l = tasks.length; 
 
    while (i < l && tasks[i].id !== id) i++; 
 
    if (i === l) { 
 
    // not found 
 
    } 
 
    else { 
 
    task = tasks[i]; 
 
    alert(task.label + ': ' + task.description); 
 
    } 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.2/handlebars.min.js"></script> 
 
<script id="source" type="text/x-handlebars-template"> 
 
    {{#each tasks}} 
 
    <button 
 
    type="button" 
 
    class="task" 
 
    style="margin-right:.5em" 
 
    onclick="onClick({{id}})" 
 
    >{{label}}</a> 
 
    {{/each}} 
 
</script> 
 
<div id="placeholder"></div>

+0

@wawawared, спасибо за вашу идею! Тем не менее, я несколько насторожен, используя индексы для асинхронной ссылки, так как даже если массив _shouldn't_ изменился без повторного вызова рендеринга, он все равно приносит в код возможную точку отказа (по сравнению с простым закрытием). Но ну, похоже, в этом случае нет идеального решения. –

+0

@EinoGourdin Добро пожаловать :-) Вы можете избежать использования индексов, если хотите, это значение «или любая другая информация». Я заменил индекс идентификатором, проверьте обновление :-) – leaf