这是我关于 SO 的第一个问题,所以我希望我没有搞砸。我已经检查了有关此问题的其他主题,但它们并未涵盖我遇到的情况。
我正在 Backbone 之上构建一个库来创建移动应用程序。我将所有组件定义为主干视图的主要原因是因为我想对滚动进行内存优化(隐藏内容/从 DOM 中删除内容)。
让我从最理想情况的防守开始
定义一个基类供其他组件使用,其中包含一些我在每个组件上需要的默认属性和一些方便的方法。
UI.Component = Backbone.View.extend({
viewOptions: ['children'],
children: [],
add: function(child) {
this.children.push(child);
}
});
定义具有一些默认属性的组件
UI.Header = UI.Component.extend({
viewOptions: ['titleBarChildren', 'secondaryBarChildren', 'title', 'backButtonTitle'],
titleBarChildren: [],
secondaryBarChildren: [],
title: '',
backButtonTitle: 'Back'
});
制作一个默认标题以在我的应用程序中使用
MyApp.Headers.Default = UI.Header.extend({
backButtonTitle: 'Terug',
titleBarChildren: [
new UI.SegmentedController({
children: [
new UI.Button('Lame example')
]
})
]
});
使用我的导航栏
var homePageNavbar = new MyApp.Header.Default({
title: 'Homepage'
});
现在让我们运行
console.log(homePageNavbar);
想象一下我们得到这个输出
// My properties, all nicely inherited
viewOptions: Array[5] //['children', 'titleBarChildren', 'secondaryBarChildren', 'title', 'backButtonTitle']
children: Array[0],
titleBarChildren: Array[1],
secondaryBarChildren: Array[0],
title: "Homepage",
backButtonTitle: "Terug"
// Some stuff that backbone assigns
$el: jQuery.fn.jQuery.init[1]
cid: "view12"
el: HTMLDivElement
options: Object
__proto__: ctor
这就是我最终想要得到的结果,但这需要一些超出我经验的魔法。
附带说明一下,我尝试对所有自定义内容使用“选项”属性,但问题是当我创建多个视图实例时,选项是“共享的”/相互引用。
所以现在我希望我对“viewOptions”方法有更多的运气,然后覆盖_configure 方法
最好这一切都在 UI.Component 或其子级中完成。我不希望这个库的用户在他们的标题定义(MyApp.Headers.Default = UI.Header.extend)中添加一些“样板代码”来扩展选项或其他任何东西。
现在我必须以某种方式从所有“后代”中获得所有属性。我完全不知道该怎么做。我曾尝试跟踪骨干中幕后发生的事情,但我无法理解它。
因此,非常感谢有关完成此操作的提示/技巧,也非常欢迎替代方法或不符合我的确切要求的方法。
编辑 1
看起来我有一些“有点”有效的东西,这就是它的样子
我重写了 _configure 方法,将选项添加到实例中,注意 this.getDefaultOptions() 作为 _.extend 中的第一个参数
UI.Component = Backbone.View.extend({
_configure: function(options) {
var viewOptions = this.viewOptions;
options = _.extend(this.getDefaultOptions ? this.getDefaultOptions() : {}, this.options || {}, options || {});
for (var i = 0, l = viewOptions.length; i < l; i++) {
var attr = viewOptions[i];
if (options[attr]) this[attr] = options[attr];
}
this.options = options;
}
});
我将这个新方法添加到我的所有组件中,并且没有将“共享”属性放在我的基础对象(UI.Component)中,因为我无法让它发挥得很好。
UI.Header = UI.Component.extend({
viewOptions: ['children', 'backButtonTitle', 'title'],
getDefaultOptions: function() {
return {
children: []
};
},
});
现在,我用这样的东西来定义我的标题
MyApp.Headers.Default = UI.Header.extend({
options: {
backButtonTitle: 'Terug',
titleBarChildren: [
new UI.SegmentedController({
children: [
new UI.Button('Lame example')
]
})
]
}
});
我会保持它现在的样子,看看这个“解决方案”是否存在,并会报告。如果您认为自己有更好的答案,请不要犹豫发布它=)
编辑
这是我最新的方法,使用 jQuery 的深拷贝,似乎可以正常工作
var UI = {};
var App = {
Headers: {}
};
UI.Component = Backbone.View.extend({
blockDefaults: {
children: []
},
initialize: function(options) {
var combinedDefaultsAndOptions = $.extend(true, {}, this.blockDefaults || {}, this.defaults || {}, this.options || {}, options || {});
_.defaults(this, combinedDefaultsAndOptions);
}
});
UI.Header = UI.Component.extend({
defaults: {
backButton: null,
backButtonTitle: null,
secondaryBarChildren: []
}
});
App.Headers.Default = UI.Header.extend({
options: {
backButtonTitle: "App back",
secondaryBarChildren: ["App child"]
}
});
var header1 = new UI.Header({
backButtonTitle: "Header 1 Back",
secondaryBarChildren: ["Header 1 child"]
});
var header2 = new UI.Header({
backButtonTitle: "Header 2 Back",
secondaryBarChildren: ["Header 2 child"]
});
var header3 = new App.Headers.Default({
});
var header4 = new App.Headers.Default({
backButtonTitle: "Overrided App Back"
});
header1.secondaryBarChildren.push('a child for header 1');
console.log(header1, header2, header3, header4);