Итератор RactiveJS с поведением по клику

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

Служба передает моему приложению объект JSON, который выглядит примерно так

var data = {
    "users": {
        "Aaron": {
            "age": "31",
            "level": "legit",
            "talk": function(){
                console.log("Howdy! I'm " + this.level);
            }
        },
        "Pete": {
            "age": "30",
            "level": "godlike",
            "talk": function(){
                console.log("Howdy! I'm " + this.level);
            }
        }
    }
};

Мой шаблон кажется правильным. Как указано в Документация

var usersTemplate = "<ul>{{#users:name}}<li><a href='#' on-click='talk'>{{name}} says:</li>{{/users}}</ul>";

Затем я создаю новый экземпляр Ractive

var people = new Ractive({
    el: "#userlist",
    template: usersTemplate ,
    data: data
});

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

people.on({
    talk: function(evt){
        evt.original.preventDefault();
        console.log("I clicked on the template");
    }
});

Что я пытаюсь сделать, так это запустить функцию action внутри объекта данных, который я передал, при этом контроллер не знает, как называется метод. Достаточно указать его в шаблоне и в объекте данных.

Ractive дает достаточно информации, чтобы я мог пройтись по объекту данных, но этого недостаточно.

people.on({
    talk: function( evt ) {
        evt.original.preventDefault();
        var pointer = json_output;
        var path = evt.keypath.split(".");
        for( var i = 0; i < path.length; i++){
            console.log(i);
            pointer = pointer[path[i]];
        }
        if(pointer.hasOwnProperty("action") && typeof(pointer.action) === "function") {
            pointer.action(evt);
        }
    }
});

Пример JSBin

Разве RactiveJS не подходит для этой работы? Заранее благодарю за помощь в поисках.


person Cmndo    schedule 31.07.2014    source источник
comment
вы видели proxy events часть документов? event.context о чем вы спрашиваете?   -  person vittore    schedule 31.07.2014
comment
Привет, витторе. Спасибо за внимание к моему вопросу. Чтобы ответить на ваш вопрос, да. Я видел документацию о прокси-событиях. Проблема в том, что я хочу, чтобы каждая кнопка выполняла разные действия, и я мог бы не знать заранее, как называется событие.   -  person Cmndo    schedule 31.07.2014
comment
Можете ли вы расширить это в вопросе, потому что для того, что я вижу сейчас, моего ответа, кажется, достаточно.   -  person vittore    schedule 31.07.2014


Ответы (3)


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

<a on-click="call:talk">Talk</a>
var ractive = new Ractive({
    el: "#userlist",
    template: usersTemplate,
    data: data
});

ractive.on('call', function ( event, method ) {
    event.context[method]();
});
person Martin Kolárik    schedule 31.07.2014
comment
Это отличное решение. Однако для этого примера требуется небольшая настройка: поскольку функция ссылается на this, ее нужно вызывать как метод: jsfiddle.net/rich_harris/N5a2Y. В противном случае он регистрирует «Привет! Я не определен» jsfiddle.net/rich_harris/Xf5pm/1 - person Rich Harris; 01.08.2014
comment
Сладкий. Спасибо. Это сработает. @RichHarris, чтобы узнать, почему Ractive не поддерживает вызов функций напрямую, где директива on-click удаляется во время синтаксического анализа? - person Cmndo; 01.08.2014
comment
@Cmndo Не столько директива по клику удаляется, сколько то, что она никогда не «добавляется» - директивы (по клику, вступление, декоратор и т. д.) являются частью виртуального DOM, но никогда не отображаются в реальном DOM. - это полностью отличается от атрибута старой школы onclick. Существует соответствующее обсуждение на GitHub прямого вызова функций, хотя оно относится к вызов методов компонента, а не функций внутри объекта данных. - person Rich Harris; 01.08.2014

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

 people.on({
     talk: function( evt ) {
         evt.original.preventDefault();
         evt.context.talk(evt)
     }
 });

кроме того, вы можете подумать о более meta способе сделать это:

 function getProxyHandler(eventName) {
    return function(event) {
       event.context[eventName](event)
    }
 }

таким образом, ваши события могут быть назначены так:

 people.on({ 
     talk:getProxyHandler('talk'), 
     eat: getProxyHandler('eat') 
 })

Используя пользовательские события, @Martin показал, что вы можете изменить обработчик для применения или вызова функции в событии следующим образом:

 people.on('call' , function(event, method) {
      method.call(event.context)
 })  
person vittore    schedule 31.07.2014
comment
Я очень ценю вашу помощь в сужении поиска. С тем, что я делаю, было бы огромной помощью, если бы объект, в котором хранятся события, которые передаются people.on, создавал себя из методов, указанных в шаблоне. - person Cmndo; 01.08.2014
comment
@Cmndo Я добавил пример того, что можно сделать, чтобы решить вашу проблему с помощью решения Мартина. - person vittore; 01.08.2014
comment
Спасибо за вашу помощь, я смотрю на это. - person Cmndo; 01.08.2014

Есть ли способ автоматизировать создание объекта, который вы передаете people.on(), учитывая значение атрибутов шаблона по клику? Ractive удаляет эти атрибуты по клику

В противном случае что-то вроде этого может быть взломано вместе с jQuery

var people = new Ractive({
    el: "#userlist",
    template: usersTemplate,
    data: data,
    complete: function(){
        var onHandler = {}, action;

        $("[on-click]", "#userlist").each(function(e){

            action = $(this).attr('on-click');
            onHanlder[action] = getProxyHandler(action);

       });

    this.on(onHandler);
  }
});
person Cmndo    schedule 31.07.2014