Backbone.js TypeError:无法读取undefined的属性

时间:2016-05-24 20:23:19

标签: javascript jquery backbone.js

我正在尝试使用Backbone.js并且很新,但是无法在以下代码中的View初始化函数中正确绑定this.listenTo。

这个骨干代码是一个单独的js文件。

    'use strict';

let Preloadcart = function ( $, Backbone, _ ) {
  // console.log(Backbone);
  console.log(this);
  let
    // fnSelf = this,
    // Model-each unit comprises of this
    Service = Backbone.Model.extend({
      defaults:{
        title:'',
        price: 0,
        checked: false
      },

      type: 'Service',

      toggleCheck: () => {
        this.set('checked', !this.get('checked'));
      }
    }),

    // Collection- of such Service instances
    ServiceList = Backbone.Collection.extend({

      // collection based on this model
      model: Service,

      type: 'ServiceList',

      // get model instances with attribute checked=true
      getChecked: () => {
        console.log(`checking ${this.type}`);
        return this.where({checked:true});
      },
    }),

    services = new ServiceList([
            new Service({ title: 'web development', price: 200}),
            new Service({ title: 'web design', price: 250}),
            new Service({ title: 'photography', price: 100}),
            new Service({ title: 'coffee drinking', price: 10})
            // Add more here
        ]),

    // View of each Service model unit
    ServiceView = Backbone.View.extend({
      tagName: 'li',

      type: 'ServiceView',

      events: {
        'click': 'toggleService'
      },

      initialize: () => {
        console.log(`initializing ${this.type}`);
        _.bindAll(this, 'toggleService', 'render');

        this.listenTo(this.model, 'change', this.render);
      },

      toggleService: () => {
        this.model.toggle();
      },

      render: () => {
        let
          $frag = $(document.createDocumentFragment()),
          $htmlCheckbox = $('<input>', {
            type:'checkbox',
            value: 1,
            name: this.model.get('title'),
          }),
          $htmlSpan = $('<span>', {
            value: `\$${this.model.get('price')}`,
          });

        $htmlCheckbox.append(this.model.get('title'));
        $htmlCheckbox.append($htmlSpan);
        this.$htmlCheckbox.prop('checked', this.model.get('checked'));

        $frag.append($htmlCheckbox);
        this.$el.append($frag);

        return this;
      }
    }),

    App = Backbone.View.extend({
      el: $('#main'),

      type: 'App',

      initialize: function () {
        // listen on the collection instance of ServiceList, services
        console.log(`initializing App ${this.type}`);
        let
          view, that= this;
        this.total = 0,
        this.collection = services;

        _.bindAll(this, 'render');

        this.listenTo(this.collection, 'change', this.render);

        _(this.collection.models).each( (model) => {
          view = new ServiceView();
          view.set({model: model});
          that.$('#services').append(view.render().el);
        }, this);
      },

      render: () => {

        _.each(this.collection.getChecked(), (each) => {
          this.total += each.get('price');
        });

        this.$('#total-value').text(`\$${this.total}`);
      }
    }),

    AppView = new App();

  // new App();
  // return App;

};


export default Preloadcart;

这在主js文件中调用如下:

$(() => {
          Preloadcart($, Backbone, _, that);
        });

但抛出错误:

preloadCart.js:57 Uncaught TypeError: Cannot read property 'type' of undefined

我在错误日志中跟踪的问题似乎在这里:

_.bindAll(this, 'toggleService', 'render');

console.log(`initializing ${this.type}`);

在ServiceView intialize函数下;

输出时,

this未定义。我错过了什么?

如果对代码有任何疑惑,请告诉我,我会尽量使这更简单。

1 个答案:

答案 0 :(得分:1)

initialize: () => {
        console.log(`initializing ${this.type}`);
        _.bindAll(this, 'toggleService', 'render');

        this.listenTo(this.model, 'change', this.render);
      },

定义初始化函数时调用箭头操作符。 就在调用Preloadcart的时候。所以在函数初始化中,&#39;这个&#39;不是观点对象,而是&#39;这个&#39;当Preloadcart被调用时。使用正常功能。

initialize: function() {
            console.log(`initializing ${this.type}`);
            _.bindAll(this, 'toggleService', 'render');

            this.listenTo(this.model, 'change', this.render);
          },