Require.js Backbone加载视图问题

时间:2014-12-09 20:02:08

标签: backbone.js model-view-controller requirejs

我有一个骨干项目,我正在转换为require.js,所以我可以学习如何使用它。我的骨干项目在转换前工作正常。我已经完成并将项目转换为使用require.js,但是这样做我从app.js加载到我的视图中的静态数据是不可见的。此外,我无法在index.html上显示从表单添加的任何新数据。

有些东西阻碍了观看。我一直收到错误" Uncaught TypeError:undefined不是函数"我在控制台中的app.js文件的第17行。以下是我的文件。我很确定我在概念上遗漏了一些东西,并且任何帮助我理解为什么我不能让它工作的输入将非常感激。


的index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Inventory App</title>

    <link rel="stylesheet" href="assets/less/style.css">
</head>
<body>
  <div id="items">
    <form class="item_form" id="addItem" action="#" name="item_form">
      <div>
          <ul>
            <li>
                 <h2>Inventory App</h2>
                 <span class="required_notification">* Denotes Required Field</span>
            </li>
            <li>
                <label for="component">Component:</label>
                <input type="text" name="component" id="component"placeholder="Component" required/>
            </li>
            <li>
                <label for="stockQty">Stock Qty:</label>
                <input type="number" name="stockQty" id="stockQty"placeholder="Stock Qty" required/>
            </li>
            <li>
                <label for="reorderQty">Reorder #:</label>
                <input type="number" number="reorderQty" id="reorderQty" placeholder="Reorder #" required/>
            </li>
            <li>
                <label for="qtyPerCrane">Qty per Crane:</label>
                <input type="number" name="qtyPerCrane" id="qtyPerCrane" placeholder="Qty per Crane" required/>
            </li>
            <li>
                <label for="vendorId">Vendor Id:</label>
                <input type="number" name="vendorID" id="vendorID" placeholder="Vendor ID" required/>
            </li>
            <li>
               <button class="submit" id="add" >Add</button>
            </li>
          </ul>
        </div>
      </form>

<!-- Label Html goes here-->
      <table id="inventory-grid">
        <thead>
          <tr>
            <th>Component</th>
            <th>Stock Qty</th>
            <th>Qty Per Crane</th>
            <th>Reorder Qty</th>
            <th>Vendor ID</th>
            <th>&nbsp;</th>
          </tr>
        </thead>
        <tbody id="inventory-holder"></tbody>
      </table>
  </div>

<!-- render inventory items-->
  <script id="inventoryTemplate" type="text/template">
      <td>  <%= component %>                                </td>
      <td>  <%= stockQty %>                                 </td>
      <td>  <%= qtyPerCrane %>                              </td>
      <td>  <%= reorderQty %>                               </td>
      <td>  <%= vendorID %>                                 </td>
      <td>  <button class="delete">Delete</button>          </td>
 </script>

  <script data-main='js/main' src="js/lib/require.js"></script>

</body>
</html>

main.js

//configure RequireJS 
requirejs.config({
    paths: {
        jquery: 'lib/jquery',
        backbone: 'lib/backbone',
        localStorage: 'lib/backbone.localStorage',
        underscore: 'lib/underscore',
        views: 'views',
        models: 'models',
        collections: 'collections'

    }, 

      // Shim declaration
    'shim': {
        'underscore': {
          'exports': '_'
        },
        'backbone': {
          'deps': ['jquery', 'underscore'],
          'exports': 'Backbone'
        }
    }
});

// call app.js to load static data 
define(['app'], function(AppView) {

var AppView = new AppView();

});

app.js

// load view with data
define (['jquery', 'backbone'], function($,Backbone) {

    var app = app || {};

    $(function() {
        var inventory = [
            { component: 'bottom bracket', stockQty: '22', reorderQty: '15', qtyPerCrane: '13', vendorID: 'Foster Machine' },
            { component: 'bottom bracket', stockQty: '22', reorderQty: '15', qtyPerCrane: '13', vendorID: 'Foster Machine' },
            { component: 'bottom bracket', stockQty: '22', reorderQty: '15', qtyPerCrane: '13', vendorID: 'Foster Machine' },
            { component: 'bottom bracket', stockQty: '22', reorderQty: '15', qtyPerCrane: '13', vendorID: 'Foster Machine' },
            { component: 'bottom bracket', stockQty: '22', reorderQty: '15', qtyPerCrane: '13', vendorID: 'Foster Machine' }
        ];

        console.log('inventory loaded');

       // THIS IS WHERE THE ERROR GETS THROWN
        new app.InventoryView( inventory );
    });
}); 

item.js(views)

// site/js/views/item.js

define(['jquery', 'backbone'], function($, Backbone) {

    var app = app || {};

    app.ItemView = Backbone.View.extend({
        tagName: 'tr',
        className: 'itemContainer',
        template: _.template( $( '#inventoryTemplate' ).html() ),

        events: {
        'click .delete': 'deleteItem'
        },

        deleteItem: function() {
            //Delete model
            this.model.destroy();

            //Delete view
            this.remove();
        },

        render: function() {
            //this.el is what we defined in tagName. use $el to get access to jQuery html() function
            this.$el.html( this.template( this.model.attributes ) );

            return this;
        }
    });

});

inventory.js(views)

// site/js/views/inventory.js

define(['jquery', 'backbone'], function($, Backbone) {

    var app = app || {};

    app.InventoryView = Backbone.View.extend({
        el: '#items',

        initialize: function( initialInventory ) {
            this.collection = new app.Inventory( initialInventory );
            this.listenTo( this.collection, 'add', this.renderItem );
            this.render();
        },
        events:{
        'click #add':'addItem'
        },

        addItem: function( e ) {
            e.preventDefault();

            var formData = {};

            $( '#addItem li' ).children( 'input' ).each( function( i, el ) {
                if( $( el ).val() != '' )
                {
                    formData[ el.id ] = $( el ).val();
                }
            });

            this.collection.add( new app.Item( formData ) );
        },

        // render inventory by rendering each book in its collection
        render: function() {
            this.collection.each(function( item ) {
                this.renderItem( item );
            }, this );
        },

        // render an item by creating an ItemView and appending the
        // element it renders to the inventory's element
        renderItem: function( item ) {
            var itemView = new app.ItemView({
                model: item
            });
            this.$el.find('#inventory-holder').append( itemView.render().el );
        }
    });

});

item.js(models)

// site/js/models/item.js

define(['jquery', 'backbone'], function($, Backbone) {

    var app = app || {};

    app.Item = Backbone.Model.extend({
        defaults: {
            component: 'no component',
            stockQty: 'no stock qty',
            reorderQty: 'no reorder qty',
            qtyPerCrane: 'qty per crane',
            vendorID: 'vendor ID'
        }
    });

});

inventory.js(馆藏)

// site/js/collections/inventory.js

define(['jquery', 'backbone'], function($, Backbone) {

    var app = app || {};

    app.Inventory = Backbone.Collection.extend({
        model: app.Item
    });

});

2 个答案:

答案 0 :(得分:0)

我建议您研究一个示例骨干/ requirejs应用程序,以获得一种感觉,我推荐这个优秀的项目:https://github.com/BenjaminAdams/RedditJS/blob/master/public/js/app/App.js

因此,您定义应用程序的方式是:

// app.js
define(["jquery", "backbone"], function($, Backbone) {
  // not exactly this but similar define your app here.  
  // get rid of all of this: `var app = app || {};`
  var App = new Backbone.application();

  // don't forget to return the Backbone App.
  return App;
});

定义骨干视图:

// sampleView.js
define(["App", "backbone", "hbs!template/comment"], function(App, Backbone, commentTmpl) {
  // Use the variable App safely here rather than `var app = app || {};`
  return Backbone.View.extend({});
});

定义骨干控制器:

define(["App", "backbone"], function(App, Backbone) {
  return Backbone.Controller.extend({});
});

定义backbone router

define(["App", "backbone"], function(App, Backbone) {
  var AppRouter = Backbone.AppRouter.extend({});

  return AppRouter;
});

最后使用requirejs require函数启动:例如(参见here

require(["App", "router", "jquery", "backbone"], function(App, AppRouter) {
  App.appRouter = new AppRouter();
  App.start();
});

请注意,这只是一个虚拟示例,您应该了解并将其应用于您的应用程序主干方式。

答案 1 :(得分:0)

新app.InventoryView(库存);会抛出错误,因为它在app.js中未定义。

您需要在app.js中加载InventoryView.js,如

   define (['jquery', 'backbone', 'InventoryView'], function($,Backbone,InventoryView) {

        var app = app || {};

        $(function() {
            var inventory = [
                { component: 'bottom bracket',.... },....... Your Code

            ];

            console.log('inventory loaded');
          app.InventoryView = InventoryView( inventory );

    // AND NOW YOU CAN CALL YOUR LINE
              new app.InventoryView();

        });
    }); 

使用RequireJS时,您必须加载文件(确保它返回一些值)并在内联函数中引用它并使用它。