- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有大量的 View (超过 50 个),它们都是从一个抽象的基础 View 扩展而来的,因此具有相似的布局和许多其他共同的特性(事件处理程序、一些自定义方法和属性等)。
我目前正在使用我的基本 View 的 initialize
方法来定义布局,它涉及一个 subview ,有点像下面这样:
App.BaseView = Backbone.View.extend({
//...
initialize: function() {
this.subView = new App.SubView();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
this.subView.$el = this.$('#subview-container');
this.subView.render();
return this;
},
//...
});
但是,我发现对于许多扩展我的基本 View 的 View ,我需要重写 initialize
方法,该方法调用基类 initialize
(我还扩展了我的events
也经常散列)。我不喜欢这样做,尤其是有这么多扩展基类的 View 。
在this post来自 Backbone Github 存储库问题 Derick Bailey 说:
I'm also not a fan of requiring extending classes to call super methods for something like
initialize
. This method is so basic and so fundamental to any object that extends from a Backbone construct. It should never be implemented by a base type - a type that is built with the explicit intent of never being instantiated directly, but always extended from.
所以在这个模型上,我应该能够为每个继承的 View 类提供一个 initialize
。这对我来说很有意义;但是我怎样才能实现我继承 View 所需的那种总体布局呢?在 constructor
方法中?
我不知道我想要的东西是否可以通过像 Marionette 或 LayoutManager 这样的东西开箱即用,我已经简要地看过但从未使用过这两者,但我更喜欢目前在 vanilla Backbone 中执行此操作。
最佳答案
我喜欢的做法是在构造函数中初始化基类,将initialize
函数留空。这是有意义的 initialize
function is only a convenience由 Backbone 提供,实际上只是构造函数的扩展。
其实Backbone做的很多。我们经常重写的大多数(如果不是全部)函数和属性只是为了方便重写。
以下是此类示例的快速列表:
初始化
,默认值
,idAttribute
,验证
,urlRoot
, 解析
等初始化
,url
,模型
,modelId
,比较器
, 解析
等initialize
, attributes
, el
, template
, render
, 事件
、className
、id
等这些函数留给用户来实现他自己的行为,并在基类中保留有用的模式,它们应该保持不变,如果可能的话,基类的行为应该 Hook 到其他函数中。
有时,这可能会变得困难,比如如果您想在 constructor
中调用 initialize
之前,但在设置元素和其他属性之后做一些事情。在这种情况下,覆盖 _ensureElement
( line 1223 )可能是一个可能的钩子(Hook)。
_ensureElement: function() {
// hook before the element is set correctly
App.BaseView.__super__._ensureElement.apply(this, arguments);
// hook just before the initialize is called.
}
这只是一个示例,几乎总有一种方法可以在基类中获得您想要的内容,而无需覆盖子类也将覆盖的函数。
如果基础 View 在一个小组件中使用并且被少数 subview 覆盖,并且大部分由同一程序员使用,那么下面的基础 View 就足够了。使用 Underscore's _.defaults
和 _.extend
将子类属性与基类合并。
App.BaseView = Backbone.View.extend({
events: {
// default events
},
constructor: function(opt) {
var proto = App.BaseView.prototype;
// extend child class events with the default if not already defined
this.events = _.defaults({}, this.events, proto.events);
// Base class specifics
this.subView = new App.SubView();
// then Backbone's default behavior, which includes calling initialize.
Backbone.View.apply(this, arguments);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
// don't set `$el` directly, use `setElement`
this.subView
.setElement(this.$('#subview-container'))
.render();
// make it easy for child view to add their custom rendering.
this.onRender();
return this;
},
onRender: _.noop,
});
不要直接设置$el
,使用setElement
相反。
然后是一个简单的 subview :
var ChildView = App.BaseView.extend({
events: {
// additional events
},
initialize: function(options) {
// specific initialization
},
onRender: function() {
// additional rendering
}
});
如果您遇到以下情况之一:
render
是有问题的,不喜欢onRender
events
属性(或任何其他属性)是子级或父级或两者中的函数然后可以将子属性实现包装到新函数中并且Underscore's _.wrap
函数就是这样做的。
App.BaseView = Backbone.View.extend({
// works with object literal or function returning an object.
events: function() {
return { /* base events */ };
},
// wrapping function
_events: function(events, parent) {
var parentEvents = App.BaseView.prototype.events;
if (_.isFunction(parentEvents)) parentEvents = parentEvents.call(this);
if (parent) return parentEvents; // useful if you want the parent events only
if (_.isFunction(events)) events = events.call(this);
return _.extend({}, parentEvents, events);
},
constructor: function(opt) {
var proto = App.BaseView.prototype;
// wrap the child properties into the parent, so they are always available.
this.events = _.wrap(this.events, this._events);
this.render = _.wrap(this.render, proto.render);
// Base class specifics
this.subView = new App.SubView();
// then Backbone's default behavior, which includes calling initialize.
Backbone.View.apply(this, arguments);
},
/**
* render now serves as both a wrapping function and the base render
*/
render: function(childRender) {
// base class implementation
// ....
// then call the child render
if (childRender) childRender.call(this);
return this
},
});
因此 child 在保持基类行为的同时看起来完全正常。
var ChildView = App.BaseView.extend({
events: function() {
return {
// additional events
};
},
initialize: function(options) {
// specific initialization
},
render: function() {
// additional rendering
}
});
如果您想完全覆盖基类行为,这可能会成为一个问题,您需要在子类中手动取消一些基类行为,这可能会造成混淆。
假设您有一个特殊的 child 使用过一次,需要完全覆盖 render
:
var SpecialChildView = App.BaseView.extend({
initialize: function(options) {
// Cancel the base class wrapping by putting
// the this class's prototype render back.
this.render = SpecialChildView.prototype.render;
// specific initialization
},
render: function() {
// new rendering
}
});
所以这不是非黑即白的,我们应该评估需要什么,什么会阻碍并选择正确的覆盖技术。
关于javascript - 在没有初始化方法的情况下定义 subview ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40982422/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!