【问题标题】:How can I select an element that will exist in future with jQuery?如何使用 jQuery 选择将来存在的元素?
【发布时间】:2011-07-15 04:45:05
【问题描述】:

我有一个要添加元素的 SVG。而在mousemove这个元素应该会移动,所以我想选择未来存在的元素:

// #svgcanvas exist always
// #templine will exist in the future
$('#svgcanvas').bind('mousemove', function(e) {         
    $('#templine').setAttributeNS(null, "x2", e.pageX);
    $('#templine').setAttributeNS(null, "y2", e.pageY);
});

这是在 click 事件上创建的 #templine 元素:

$('#svgcanvas').bind('click', function(e) {
    var line = document.createElementNS(xmlns, "line");
    line.setAttributeNS(null, "id", "templine");
    line.setAttributeNS(null, "x1", points[0].x);
    line.setAttributeNS(null, "y1", points[0].y);
    line.setAttributeNS(null, "x2", e.pageX);
    line.setAttributeNS(null, "y2", e.pageY);
    line.setAttributeNS(null, "style", "stroke:rgb(100,100,100)");
    document.getElementById('canvas').appendChild(line);
});

此代码不起作用,因为#templine 在绑定时不存在。有没有其他方法可以用 jQuery 解决这个问题?我曾尝试使用.live() 而不是.bind(),但这在这种情况下没有帮助。

【问题讨论】:

  • 不,如果这是您的问题,还有其他问题。 $('#templine') 将在每个事件上一次又一次地执行(顺便说一下,这可能会对性能产生影响)。为什么您认为这是问题所在而不是其他问题?
  • 我从你的代码中猜测会有多个templine 元素,所以使用class 属性而不是id 属性。
  • 顺便说一句:我相信您的 svgcanvas/click 函数的最后 7 行可以缩短为 $(line).attr('id', '#templine').attr('x1',points[0].x).attr('y1', points[0].y).attr('x2', e.pageX).attr('y2', e.pageY).attr('style', 'stroke:rgb(100,100,100)').appendTo('#canvase');。如果 jQuery 在 svg 上的行为不奇怪...
  • @yankee:我希望在每个 mousemove 事件上执行 $('#templine'),因为当鼠标移动时该行应该改变。所以我觉得是对的。根据您的建议,我会尽量缩短我的代码,谢谢。
  • @waitinforantrain:这段代码很简单,我只会在第一次点击时创建一个id为“templine”的元素。

标签: javascript jquery jquery-selectors svg


【解决方案1】:

我看到的问题是$('#templine') 是一个jQuery 对象,因此没有setAttributeNS 方法。

试试这个:

$('#templine').attr("x2", e.pageX);
$('#templine').attr("y2", e.pageY);

【讨论】:

  • 很好,但这不是OP提到的问题
  • @Juan:是的。 “因为 #templine 在绑定时不存在”是不正确的。该事件绑定到存在的$('#svgcanvas'),所以没关系。当函数运行时,$('#templine') 将返回一个 jQuery 对象(如果元素不存在,它可能为空,但它仍然是一个有效的 jQuery 对象)。 jQuery 对象没有 setAttributeNS.
  • 别这么认为,在您单击#svgcanvas 之前不会创建#templine。您不必再次解释 OP 正在尝试在 jQuery 对象上调用 HTMLElement 方法。
  • @Juan:#templine 存在与否有什么关系?如果你试图在一个空的 jQuery 对象上调用一个函数,它就什么也做不了。如果你调用一个不存在的函数,它会抛出错误并崩溃。
  • @Rocket:哇,我完全错过了。您可能想建议使用 attr() 而不是 setAttributeNS...
【解决方案2】:

试试这个:

$('#canvas').bind('click', function(e) {
    var line = document.createElementNS(xmlns, "line");
    line.setAttributeNS(null, "id", "templine");
    line.setAttributeNS(null, "x1", points[0].x);
    line.setAttributeNS(null, "y1", points[0].y);
    line.setAttributeNS(null, "x2", e.pageX);
    line.setAttributeNS(null, "y2", e.pageY);
    line.setAttributeNS(null, "style", "stroke:rgb(100,100,100)");
    document.getElementById('canvas').appendChild(line);
    $('#svgcanvas').bind('mousemove', function(e) {         
        line.setAttributeNS(null, "x2", e.pageX);
        line.setAttributeNS(null, "y2", e.pageY);
    });
});

另外,@Rocket 的建议也是有效的。更新我的答案...

【讨论】:

  • 你应该加入 Rocket 的建议:$(...)[0].setAtttribute...
  • 注意点。我在发布答案后注意到了这一点。
  • 为了提高性能,我会使用line.setAttributeNS,而不是每次鼠标移动都查询 DOM 两次
  • 谢谢 agn!显然,我今天的大脑工作不正常!再次更新!
【解决方案3】:

两种选择:

  • 处理程序检查“#templine”是否存在,如果不存在,则不执行任何操作。
  • 在创建#templine(在第二个处理程序的底部)之前不要安装处理程序

另外,不要连续调用两次$('#templine'),将结果保存在一个变量中。

【讨论】:

    猜你喜欢
    • 2012-08-26
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 2011-11-19
    • 2012-04-12
    • 2012-05-17
    • 1970-01-01
    相关资源
    最近更新 更多