从Javascript生成的HTML中的按钮调用JavaScript

时间:2018-08-27 18:35:54

标签: javascript backbone.js coffeescript

我有一个Ruby on Rails项目(可能不相关),其中有一个由java / coffescript生成的表。

此表的一个字段中有一个按钮,我想调用另一个javascript函数。

我看过Using an HTML button to call a JavaScript function,但似乎找不到“ if Rails.env.test? require 'factory_girl' FactoryGirl.define do factory :track do id 1 name "nurburgring" surface_type "snow" time_zone "CET" end end ”函数...

当前,我有:

doFunction

并且我还尝试将class App.Table extends Backbone.Model defaults: { showPastResults: true } initialize: -> @set("selectedCohortLabel", @get("cohortLabels")[0]) headers: => [BLAH BLAH BLAH] columns: => columns = [] [BLAH BLAH BLAH] Array::push.apply columns, [['<input id="clickMe" type="button" value="clickme" onclick="doFunction();" />', 5, 5]] if @get('haveDataBytes') columns doFunction: -> console.log("foo") 放在课堂之外。它总是给出:

doFunction

那么doFunction应该放在哪里,以便它可以在运行时找到它?

1 个答案:

答案 0 :(得分:0)

您的方法并没有真正遵循骨干架构。在骨干网中 将您的业务领域建模为“模型”和“模型集合”。如果您遵循 这条规则一切都很好地完成了。

在这种情况下,命名表Table的决定是错误的,因为表是 代表性的对象。数据本身可以以多种方式显示。

下面是一个示例,说明如何(或应该)设计应用程序 一种对Backbone.js不起作用的方法。数据被建模为集合 元素,每个元素将在表格的一行中表示。  请按照源代码中的注释进行进一步的解释。

文件:index.html(我使用npm和browserify构建应用程序,但不是 如图所示。确保提供必要的依赖项。

<!doctype html>
<html>
    <head>
        <title>Coffeescript And Backbone</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div class="container">
            <h2>Elements Table</h2>
            <div class="table"></div>
        </div>

        <script id="tablerow" type="text/x-handlebars-template">
            <td>{{id}}</td>
            <td>{{name}}</td>
            <td>{{value}}</td>
            <td><button class="button">HaveDataBytes</button></td>
        </script>

        <script src="app.js"></script>
    </body>
</html>

文件:app.coffee

# The template is integrated in index.html (script#tablerow).
# Here I read and compile the template function for the table row.
#
# This must be called after the template script is in the DOM.
#
# Using a packaging tool like browserify or webpack would allow you
# to precompile the templates during the packaging process, but this
# approach is good for small applications.
compileTemplate = (name) ->
    source = document.getElementById(name).innerHTML
    Handlebars.compile(source)

rowTemplate = compileTemplate('tablerow')

# Define the applications backbone
App =
    View: {}
    Model: {}
    Collection: {}

# This is a dummy dataset of elements that would be fetched from the server
# using the Collection abstraction. Each entry in data will be represented
# in a table view further down.
data = [
    { id: 1, name: "element1", value: "value1", haveDataBytes: true },
    { id: 2, name: "element2", value: "value2", haveDataBytes: false },
    { id: 3, name: "element3", value: "value3", haveDataBytes: true },
    { id: 4, name: "element4", value: "value4", haveDataBytes: true },
    { id: 5, name: "element5", value: "value5", haveDataBytes: false }
]

# The model element takes up each entry from data ...
class App.Model.Element extends Backbone.Model

# and is stored in a collection of Element models
class App.Collection.Elements extends Backbone.Collection
    model: App.Model.Element

与您的方法相比,模型中的标题和列具有简单列表 主要好处是所有数据都由Backbone保留和控制。 您可以简单地更新整个收藏集,聆听更改并发送事件, 将单个条目序列化到服务器,响应单个条目的更改- 完全控制...

# The table view
class App.View.ElementsTable extends Backbone.View

    # is a table by itself
    tagName: 'table'

    # it receives the collection of elements
    initialize: (options) ->
        @collection = options.collection

    # and renders each row ...
    render: ->
        @collection.each(@renderRow, @)
        @
    # ... in a element table row view
    renderRow: (row) ->
        rowView = new App.View.ElementTableRow(model: row)
        @$el.append(rowView.render().el)

#  The element table row ...
class App.View.ElementTableRow extends Backbone.View
    # ... is itself a row
    tagName: 'tr'

    # and takes an element model
    initialize: (options) ->
        @model = options.model

    # it handles the click event ...
    events: {
        'click button': 'click'
    }

    # ... with full access to the model and the collection, which is a member
    # of the element model
    click: (evt) ->
        console.log(evt.target.name, @model, @model.collection)
        @$('td').toggleClass('red')

    # render uses the precompiled handlebars template to render the row,
    # no HTML in the view or the model necessary

    render: () ->
        @$el.html(rowTemplate(this.model.toJSON()))
        # Here I show/hide the buttons based on the element models data.
        # It would definitely be better to not render the buttons in first place
        if not @model.get('haveDataBytes')
            @$('button').hide()
        @


# simple start script
$(() ->
    # 'load' the data as a collection
    collection = new App.Collection.Elements(data)

    # check the elements
    console.log(collection.models)

    # create and render the table view
    view = new App.View.ElementsTable(collection: collection)
    $('.table').append(view.render().el)
)

最后但并非最不重要的一点是,doFunction应该位于视图中(请参见 click)或由App.View.ElementTableRow的点击处理程序调用。