我正在使用Backbone处理一个应用程序,并且我遇到的问题是“el”属性是动态创建的<g>
元素。视图的代码如下:
var DependencyLineView = Backbone.View.extend({
//el: document.createElementNS(nameSpace, 'g'),
initialize: function () {
//var gElement = document.createElementNS(nameSpace, 'g');
//var gElementComplete = createShape(this.options.iteration, this.el);
var gElement = document.createElementNS(nameSpace, 'g');
var gElementComplete = createShape(this.options.iteration, gElement);
this.el = gElementComplete;
$(gElementComplete).attr('stroke-width', '1px')
.attr('stroke', 'red')
.attr('fill', 'red');
this.el = gElementComplete;
this.render();
},
render: function() {
$('#lineContainer').append(this.el);
},
events: {
"click": "clickEvent",
},
clickEvent: function(ev) {
alert('here');
},
});
如果我在初始化期间生成元素(而不是使用“el”属性),则按预期进行渲染(I.E.每次新视图得到证实和渲染时,<g>
元素都会添加到#lineContainer中。但是,如果我使用“el”属性生成元素,则无论添加新视图并渲染多少次,都只会创建一个<g>
元素。我为了演示目的编写了一个名为“createShape”的函数,它为SVG组元素添加了一些<line>
元素。以下是两种方法的结果:
在初始化期间生成元素:
<svg id="lineContainer">
<g stroke-width="1px" stroke="red">
<line x1="10" y1="10" x2="50" y2="10"></line>
<line x1="50" y1="10" x2="50" y2="50"></line>
<line x1="50" y1="50" x2="100" y2="50"></line>
</g>
<g stroke-width="1px" stroke="red">
<line x1="20" y1="20" x2="100" y2="20"></line>
<line x1="100" y1="20" x2="100" y2="100"></line>
<line x1="100" y1="100" x2="200" y2="100"></line>
</g>
</svg>
使用“el”属性生成:
<svg id="lineContainer">
<g stroke-width="1px" stroke="red" fill="red">
<line x1="0" y1="0" x2="0" y2="0"></line>
<line x1="0" y1="0" x2="0" y2="0"></line>
<line x1="0" y1="0" x2="0" y2="0"></line>
<line x1="10" y1="10" x2="50" y2="10"></line>
<line x1="50" y1="10" x2="50" y2="50"></line>
<line x1="50" y1="50" x2="100" y2="50"></line>
<line x1="20" y1="20" x2="100" y2="20"></line>
<line x1="100" y1="20" x2="100" y2="100"></line>
<line x1="100" y1="100" x2="200" y2="100"></line>
<line x1="30" y1="30" x2="150" y2="30"></line>
<line x1="150" y1="30" x2="150" y2="150"></line>
<line x1="150" y1="150" x2="300" y2="150"></line>
<line x1="40" y1="40" x2="200" y2="40"></line>
<line x1="200" y1="40" x2="200" y2="200"></line>
<line x1="200" y1="200" x2="400" y2="200"></line>
</g>
</svg>
我希望能够利用“el”属性动态生成SVG组元素,这样我就可以使用骨干本地委派的事件(并且由于其他原因,如果不仅仅是为了坚持骨干风格在JavaScript中编码)但每个组需要单独附加(不折叠,就像它在示例中所做的那样)。我做错了什么?
JSFiddle:http://jsfiddle.net/e2DJ8/1/
答案 0 :(得分:3)
当你在你的观点中这样说时:
el: document.createElementNS(nameSpace, 'g'),
您将<g>
附加到视图原型中的el
,以便所有实例共享一个<g>
,直到您更改el
为止在initialize
内。但是,在分配新的el
之前,您要这样做:
initialize: function () {
var gElementComplete = createShape(this.options.iteration, this.el);
// --------------------------------------------------------^^^^^^^
您的createShape
函数会在其第二个参数中添加内容,每次创建新DependencyLineView
时,它们都会使用与<g>
完全相同的el
您致电createShape
:视图的每个实例都没有明确的el
,它们都分享完全相同的<g>
。
创建视图“类”时没有理由指定el
,所以不要打扰,只需根据需要创建<g>
并使用setElement
将其附加到视图中:
initialize: function (options) {
var gElement = document.createElementNS(nameSpace, 'g');
var gElementComplete = createShape(options.iteration, gElement);
// ...
this.setElement(gElementComplete);
演示:http://jsfiddle.net/ambiguous/zVfJb/
请注意,我使用的是setElement
而不是直接分配给this.el
,从不自行分配给this.el
,因为它不会绑定事件处理程序或设置缓存的this.$el
1}}。另请注意,我没有使用Backbone 0.3.3,因为这是Backbone的石器时代版本,我假设您使用的是至少1.0。使用更新的Backbone还意味着this.options
不会自动在视图中设置,因此我只使用options.iteration
和options
initialize
个参数。
如果由于某种原因你坚持在视图定义中使用el
,那么将它作为一个函数,以便每个实例都有一个不同的<g>
:
el: function() {
return document.createElementNS(nameSpace, 'g');
}
演示:http://jsfiddle.net/ambiguous/GLbts/
也就是说,所有这些渲染逻辑都应该在你的视图的render
方法中(这是render
的用途,渲染); render
也通常以return this;
结尾,因此您也应该这样做。那么理想情况下你会说这样的话:
var i, var v;
for(i = 0; i < 5; ++i) {
v = new DependencyLineView({ iteration: i });
$('#lineContainer').append(v.render().el); // this is why `render` returns `this`.
}
并且您的视图根本不会触及DOM:它只会创建所需的元素,并将其留给调用者将它们放在某处。