在下划线模板中调用对象上的函数

时间:2013-08-16 08:05:05

标签: javascript templates underscore.js

我的模板的HTML中有一个按钮。如何让它在当时渲染的对象上调用函数?

我意识到this正在引用当时的按钮。但是我怎么称呼这个人?

FULL CODE: JS Fiddle

TEMPLATE

<script type="text/template" id="tpl-person">
    <tr>
        //...
        <td><button onclick="this.happyBirthday()">Birthday</button></td>
    </tr>
</script>

JAVASCRIPT

var Person = function(name, age){

    //....

    this.happyBirthday = function(){
        this.age ++;
    }

    this.render = function(){
        var template = _.template($("#tpl-person").html());
        $("#peopleWrapper").append(template(this));
    }

    //constructor
    this.name = name;
    this.age = age;
    this.render();
}

1 个答案:

答案 0 :(得分:2)

为什么这不起作用

不可能这样做,因为从HTML附加事件处理程序要求处理函数被序列化(即以源格式)。有no real way在JavaScript中序列化一个函数,即使你可以有另一个showstopper:在函数this内部是对现有JavaScript对象的引用,这是不可能的,因为再次,你所做的一切确实需要序列化。

可以做什么呢

一个简单的解决方法是在呈现模板时使用jQuery附加事件处理程序。

考虑到this的期望值,您可以在任何Person方法中定义事件处理函数

// $.proxy because otherwise "this" would be the clicked button element
$.proxy(this.happyBirthday, this);

附加点击处理程序非常简单:

var clickHandler = $.proxy(this.happyBirthday, this);
var html = $(template(this));
$("#peopleWrapper").append(html.find("button").click(clickHandler).end());

更好的方法

那就是说,这看起来不是安排事情的好方法。考虑一个不同的建议:将Person对象附加到呈现的模板(例如通过jQuery的.data)并从单击处理程序中引用它;可以委派处理程序本身来保存函数并允许动态添加更多渲染模板。

例如:

HTML模板本身根本不附加任何处理程序。

添加渲染模板时,使用.data将其与person对象关联,并执行某些操作以将其标记为从DOM透视图可见的人员关联。这可以像添加data-person属性(或CSS类)一样简单:

$("#peopleWrapper").append(
  $(template(this)).data("Person", this).attr("data-person", ""));

将委托处理程序附加到DOM,以识别按钮上的点击,并从单击的元素开始,找到关联的person对象并调用happyBirthday方法:

$("#peopleWrapper").on("click", "[data-person] button", function() {
    $(this).closest("[data-person]").data("Person").happyBirthday();
});

<强> See it in action