Backbone.js视图的默认值?

Phi*_*unt 20 javascript backbone.js

我正在努力,Backbone.js我想知道你是否可以像设置模型的默认值一样设置默认值?

dir*_*ira 31

您可以做的是在initialize函数中设置默认值.

defaults: {
  display: 'list'
},

initialize: function() {
  this.options = _.extend({}, this.defaults, this.options);
}
Run Code Online (Sandbox Code Playgroud)

这适用于普通选项,但不会覆盖任何特殊选项(Backbone也存储在视图对象上['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName'])-

查看工作演示:http://jsfiddle.net/dira/7MmQE/1/

  • 使用_.defaults()是一个更清晰的解决方案. (8认同)
  • #documentcloud上的好人指出了这个问题.this.defaults来自原型,所以它在两个实例中都是相同的对象.使用this.defaults和this.options扩展新对象可以解决问题.我已经适当地编辑了@ dira的答案. (4认同)
  • 我有同样的问题,但浏览了一段时间后.我发现这个(https://github.com/documentcloud/underscore/issues/106)this.options = _.extend({},this.defaults,this.options) (2认同)

Pet*_*ons 26

对于Backbone 1.1或更新版本

方法A:在初始化中使用_.defaults的OptionsInLiteral

var MyView = Backbone.View.extend({
  options: {
    enabled: true,
    align:   "left"
  },
  initialize: function (options) {
    #be sure to do the '|| {}' here so 'new MyView()' works
    this.options = _.defaults(options || {}, this.options);
  }
});
Run Code Online (Sandbox Code Playgroud)

方法B:使用viewOptions插件(或类似)

https://github.com/rotundasoftware/backbone.viewOptions

感谢@BraveDave在评论中指出这一点.

对于1.1版之前的Backbone(历史参考,FYI)

这是骨干问题,似乎核心团队最有可能完全摆脱this.options逻辑_configure.

使用options属性并始终使用this.options

这个问题有很多混乱,甚至是一个高度赞成和接受的错误答案.希望这个答案能够证明一个真正正确的解决方案,并指出所有其他候选答案中的错误.

要与Backbone.View父类协调工作,您应该包含options传递给的对象文字的属性Backbone.View.extend.

var OptionsInLiteral = Backbone.View.extend({
  options: {flavor: "vanilla"},
  initialize: function (options) {
    console.log("OptionsInLiteral.initialize first argument", options);
    console.log("OptionsInLiteral.initialize this.options", this.options);
  }
});
Run Code Online (Sandbox Code Playgroud)

以下是一些示例以及它们登录到控制台的内容.

new OptionsInLiteral();
    //OptionsInLiteral.initialize first argument undefined
    //OptionsInLiteral.initialize this.options Object {flavor: "vanilla"}
new OptionsInLiteral({flavor: "chocolate"});
    //OptionsInLiteral.initialize first argument Object {flavor: "chocolate"}
    //OptionsInLiteral.initialize this.options Object {flavor: "chocolate"}
new OptionsInLiteral({flavor: "strawberry", sprinkles: true});
    //OptionsInLiteral.initialize first argument Object {flavor: "strawberry", sprinkles: true}
    //OptionsInLiteral.initialize this.options Object {flavor: "strawberry", sprinkles: true}
Run Code Online (Sandbox Code Playgroud)

这将正确利用Backbone.View._configure,从Backbone 1.0.0看起来像这样:

_configure: function(options) {
  if (this.options) options = _.extend({}, _.result(this, 'options'), options);
  _.extend(this, _.pick(options, viewOptions));
  this.options = options;
},
Run Code Online (Sandbox Code Playgroud)

这意味着:

  • 如果视图对象文字包含options,_configure将正确地将它们视为默认值,使用传递给构造函数的属性覆盖它们,并将最终生成的对象设置为this.options.欢呼.这就是我们想要的.
  • 即使在没有参数的情况下调用视图构造函数,这也会起作用.欢呼.也是我们想要的.
  • 因为_.result在这里使用,options属性可以是a Object或a function,如果它是函数,它将被调用并且将使用返回值.

这也是可以接受的,并允许每个实例的默认值是唯一的.

var OptionsFunctionInLiteral = Backbone.View.extend({
  options: function () {
    return {
      flavor: "vanilla",
      created: Date(),
      collection: new Backbone.Collection()
    };
  },
  initialize: function (options) {
    console.log("OptionsFunctionInLiteral.initialize first argument", options);
    console.log("OptionsFunctionInLiteral.initialize this.options", this.options);
  }
});
Run Code Online (Sandbox Code Playgroud)

以下是一些示例以及它们登录到控制台的内容.

new OptionsFunctionInLiteral();
    //OptionsFunctionInLiteral.initialize first argument undefined
    //OptionsFunctionInLiteral.initialize this.options Object {flavor: "vanilla", created: "Wed Jun 19 2013 16:20:16 GMT-0600 (MDT)", collection: Backbone.Collection}
new OptionsFunctionInLiteral({flavor: "chocolate"});
    //OptionsFunctionInLiteral.initialize first argument Object {flavor: "chocolate"}
    //OptionsFunctionInLiteral.initialize this.options Object {flavor: "chocolate", created: "Wed Jun 19 2013 16:21:17 GMT-0600 (MDT)", collection: Backbone.Collection}
new OptionsFunctionInLiteral({flavor: "strawberry", sprinkles: true});
    //OptionsFunctionInLiteral.initialize first argument Object {flavor: "strawberry", sprinkles: true}
    //OptionsFunctionInLiteral.initialize this.options Object {flavor: "strawberry", created: "Wed Jun 19 2013 16:22:26 GMT-0600 (MDT)", collection: Backbone.Collection, sprinkles: true}
Run Code Online (Sandbox Code Playgroud)

为什么你应该总是使用this.options

因此,如果你的视图的构造函数没有参数调用,你的initialize函数内部this.options将存在并且是正确的,但函数的普通options参数将是正确的,所以上面的内容很棒.initializeundefined

initialize: function (options) {
  console.log(options.flavor); //BUG! options is undefined. Uncaught exeption. :-(
  console.log(this.options); //correct
}
Run Code Online (Sandbox Code Playgroud)

因此,当我定义初始化时,我甚options至没有将该函数的参数指定为提醒不使用它.通常,您希望忽略options参数,initialize因为它无论如何都不包含默认值.

越野车回答:_.extend(this.defaults,this.options)

这个答案有一个错误,即每次实例化实例时它都会无意中修改所有未来实例的默认值.

var DefaultsExtendView = Backbone.View.extend({
  defaults: {flavor: "vanilla"},
  initialize: function (options) {
    console.log("initialize 1st argument", options);
    this.options = _.extend(this.defaults, this.options);
    console.log("initialize this.options", this.options);
  }
});

new DefaultsExtendView(); //OK
new DefaultsExtendView({flavor: "chocolate"}); //OK
new DefaultsExtendView(); //BUG! You get chocolate instead of vanilla
Run Code Online (Sandbox Code Playgroud)

越野车答案:if(options.foo)

var myView = Backbone.View.extend({
    foo: "default_value",

    initialize: function(options) {
        if(options.foo) {
            foo = options.foo;
        }
    }
});

new myView(); //BUG! options is undefined, uncaught exception
//TypeError: Cannot read property 'foo' of undefined
Run Code Online (Sandbox Code Playgroud)

注意选项对象和特定于实例的默认值

这个问题的答案之一表明:

var DefaultsView = Backbone.View.extend({
  defaults: {
    collection: new Backbone.Collection()
  },
  initialize: function () {
    _.defaults(this.options, this.defaults);
Run Code Online (Sandbox Code Playgroud)

这几乎肯定不是你想要的和一个bug.如果你创建10个视图,它们将共享相同的实例,Backbone.Collection因为在定义视图子类时只会创建1个实例.当您将模型添加到view9的集合并且它显示在所有视图中时,这肯定会让您感到困惑.你更可能想要的是每个视图实例的不同的新集合实例,并且要获得你需要options的功能,如上例所示.

总结正确的方法来做到这一点

  1. options: {...}options: function () {...}
  2. 声明你initialize没有任何参数
  3. 访问您正确默认的选项 this.options

示例锅炉板

var MyView = Backbone.View.extend({
  options: {flavor: "vanilla"},
  initialize: function () { //note no declared arguments
      //use this.options here as needed and all is well
  }
});
Run Code Online (Sandbox Code Playgroud)

工作jsfiddle

http://jsfiddle.net/DUc25/


Bri*_*sio 13

对于Backbone 1.1或更新版本

方法A:在初始化中使用_.defaults的OptionsInLiteral

var MyView = Backbone.View.extend({
  options: {
    enabled: true,
    align:   "left"
  },
  initialize: function (options) {
    #be sure to do the '|| {}' here so 'new MyView()' works
    this.options = _.defaults(options || {}, this.options);
  }
});
Run Code Online (Sandbox Code Playgroud)

方法B:使用viewOptions插件(或类似)

backbone.viewOptions

感谢@BraveDave在评论中指出这一点.

对于1.1版之前的Backbone(历史参考,FYI)

这是骨干问题,似乎核心团队最有可能完全摆脱this.options逻辑_configure.

使用options属性并始终使用this.options

这个问题有很多混乱,甚至是一个高度赞成和接受的错误答案.希望这个答案能够证明一个真正正确的解决方案,并指出所有其他候选答案中的错误.

要与Backbone.View父类协调工作,您应该包含options传递给的对象文字的属性Backbone.View.extend.

var OptionsInLiteral = Backbone.View.extend({
  options: {flavor: "vanilla"},
  initialize: function (options) {
    console.log("OptionsInLiteral.initialize first argument", options);
    console.log("OptionsInLiteral.initialize this.options", this.options);
  }
});
Run Code Online (Sandbox Code Playgroud)

以下是一些示例以及它们登录到控制台的内容.

new OptionsInLiteral();
    //OptionsInLiteral.initialize first argument undefined
    //OptionsInLiteral.initialize this.options Object {flavor: "vanilla"}
new OptionsInLiteral({flavor: "chocolate"});
    //OptionsInLiteral.initialize first argument Object {flavor: "chocolate"}
    //OptionsInLiteral.initialize this.options Object {flavor: "chocolate"}
new OptionsInLiteral({flavor: "strawberry", sprinkles: true});
    //OptionsInLiteral.initialize first argument Object {flavor: "strawberry", sprinkles: true}
    //OptionsInLiteral.initialize this.options Object {flavor: "strawberry", sprinkles: true}
Run Code Online (Sandbox Code Playgroud)

这将正确利用Backbone.View._configure,从Backbone 1.0.0看起来像这样:

_configure: function(options) {
  if (this.options) options = _.extend({}, _.result(this, 'options'), options);
  _.extend(this, _.pick(options, viewOptions));
  this.options = options;
},
Run Code Online (Sandbox Code Playgroud)

这意味着:

  • 如果视图对象文字包含options,_configure将正确地将它们视为默认值,使用传递给构造函数的属性覆盖它们,并将最终生成的对象设置为this.options.欢呼.这就是我们想要的.
  • 即使在没有参数的情况下调用视图构造函数,这也会起作用.欢呼.也是我们想要的.
  • 因为_.result在这里使用,options属性可以是a Object或a function,如果它是函数,它将被调用并且将使用返回值.

这也是可以接受的,并允许每个实例的默认值是唯一的.

var OptionsFunctionInLiteral = Backbone.View.extend({
  options: function () {
    return {
      flavor: "vanilla",
      created: Date(),
      collection: new Backbone.Collection()
    };
  },
  initialize: function (options) {
    console.log("OptionsFunctionInLiteral.initialize first argument", options);
    console.log("OptionsFunctionInLiteral.initialize this.options", this.options);
  }
});
Run Code Online (Sandbox Code Playgroud)

以下是一些示例以及它们登录到控制台的内容.

new OptionsFunctionInLiteral();
    //OptionsFunctionInLiteral.initialize first argument undefined
    //OptionsFunctionInLiteral.initialize this.options Object {flavor: "vanilla", created: "Wed Jun 19 2013 16:20:16 GMT-0600 (MDT)", collection: Backbone.Collection}
new OptionsFunctionInLiteral({flavor: "chocolate"});
    //OptionsFunctionInLiteral.initialize first argument Object {flavor: "chocolate"}
    //OptionsFunctionInLiteral.initialize this.options Object {flavor: "chocolate", created: "Wed Jun 19 2013 16:21:17 GMT-0600 (MDT)", collection: Backbone.Collection}
new OptionsFunctionInLiteral({flavor: "strawberry", sprinkles: true});
    //OptionsFunctionInLiteral.initialize first argument Object {flavor: "strawberry", sprinkles: true}
    //OptionsFunctionInLiteral.initialize this.options Object {flavor: "strawberry", created: "Wed Jun 19 2013 16:22:26 GMT-0600 (MDT)", collection: Backbone.Collection, sprinkles: true}
Run Code Online (Sandbox Code Playgroud)

为什么你应该总是使用this.options

因此,如果你的视图的构造函数没有参数调用,你的initialize函数内部this.options将存在并且是正确的,但函数的普通options参数将是正确的,所以上面的内容很棒.initializeundefined

initialize: function (options) {
  console.log(options.flavor); //BUG! options is undefined. Uncaught exeption. :-(
  console.log(this.options); //correct
}
Run Code Online (Sandbox Code Playgroud)

因此,当我定义初始化时,我甚options至没有将该函数的参数指定为提醒不使用它.通常,您希望忽略options参数,initialize因为它无论如何都不包含默认值.

越野车回答:_.extend(this.defaults,this.options)

这个答案有一个错误,即每次实例化实例时它都会无意中修改所有未来实例的默认值.

var DefaultsExtendView = Backbone.View.extend({
  defaults: {flavor: "vanilla"},
  initialize: function (options) {
    console.log("initialize 1st argument", options);
    this.options = _.extend(this.defaults, this.options);
    console.log("initialize this.options", this.options);
  }
});

new DefaultsExtendView(); //OK
new DefaultsExtendView({flavor: "chocolate"}); //OK
new DefaultsExtendView(); //BUG! You get chocolate instead of vanilla
Run Code Online (Sandbox Code Playgroud)

越野车答案:if(options.foo)

var myView = Backbone.View.extend({
    foo: "default_value",

    initialize: function(options) {
        if(options.foo) {
            foo = options.foo;
        }
    }
});

new myView(); //BUG! options is undefined, uncaught exception
//TypeError: Cannot read property 'foo' of undefined
Run Code Online (Sandbox Code Playgroud)

注意选项对象和特定于实例的默认值

这个问题的答案之一表明:

var DefaultsView = Backbone.View.extend({
  defaults: {
    collection: new Backbone.Collection()
  },
  initialize: function () {
    _.defaults(this.options, this.defaults);
Run Code Online (Sandbox Code Playgroud)

这几乎肯定不是你想要的和一个bug.如果你创建10个视图,它们将共享相同的实例,Backbone.Collection因为在定义视图子类时只会创建1个实例.当您将模型添加到view9的集合并且它显示在所有视图中时,这肯定会让您感到困惑.你更可能想要的是每个视图实例的不同的新集合实例,并且要获得你需要options的功能,如上例所示.

总结正确的方法来做到这一点

  1. options: {...}options: function () {...}
  2. 声明你initialize没有任何参数
  3. 访问您正确默认的选项 this.options

示例锅炉板

var MyView = Backbone.View.extend({
  options: {flavor: "vanilla"},
  initialize: function () { //note no declared arguments
      //use this.options here as needed and all is well
  }
});
Run Code Online (Sandbox Code Playgroud)

工作jsfiddle

http://jsfiddle.net/DUc25/