事件委托在jQuery可调整大小上

huangapple go评论70阅读模式
英文:

Event Delegation on jQuery resizable

问题

我的问题比这个例子更大,但我编写了一个展示相同行为的示例测试。

问题在于如何在动态向页面添加元素后附加/重新附加可调整大小事件。我意识到可以使用类似于以下代码的点击事件来实现这一点:

$('.table1').on('click', 'tr', function() {alert("clicked!");});

当向表格添加新的 tr 并点击时,将显示警报,这使用了事件委托。然而,针对使用 jQuery Resizable 的示例似乎不适用于这种情况,那么应该如何做呢?

这是我的测试案例(为简单起见,这在单个测试文件中):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>事件委托测试</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css">
    <style>
        #resizable { width: 150px; height: 150px; padding: 0.5em; }
        #resizable h3 { text-align: center; margin: 0; }
    </style>

    <script src="//code.jquery.com/jquery-3.6.0.js"></script>
    <script src="//code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
    <script>
        jQuery(document).ready( function($) {
            $( function() {
                $(".resizable").resizable();// <--- 如何在此添加委派事件?
            } );

            $("button").click( function () {
                $("#size-region").append('<div id="2" style="width:150px; height: 100px;" class="ui-widget-content resizable"><h3 class="ui-widget-header">Not Resizable</h3></div>');
            } );
        } );
    </script>
</head>
<body>
    <div id="size-region" class="height: 90%; width: 100%;">
        <div id="1" style="width:150px; height: 100px;" class="ui-widget-content resizable">
            <h3 class="ui-widget-header">Resizable</h3>
        </div>
    </div>
    <button>点击我</button>
</body>
</html>

jQuery Resizable 的文档位于 https://jqueryui.com/resizable/

有关事件委派的信息请查看 https://learn.jquery.com/events/event-delegation/

我提到问题更大,我相信可以使用 JavaScript 添加元素,但如果我还有其他 10 个事件要添加呢?我特别寻找一种方法,可以添加一个单独的 JavaScript 文件,并在添加到 size-region 的任何内容上使用这个方法(如果可能的话)。

英文:

My problem is larger than this example but I've composed an example test which exhibits the same behaviour.

The problem, how to attach/reattach the resizable event after dynamically adding an element to the page. I realise that this can be done with click events using something like $(&#39;.table1&#39;).on(&#39;click&#39;, &#39;tr&#39;, function() {alert(&quot;clicked!&quot;);}); which will show the alert when a new tr is added to the table and it is clicked, this uses event delegation. However the examples for using jQuery Resizable do not appear to cater for this, so how can it be done?

Heres my test case (for simplicity this is in a single test file):

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;title&gt;Event Delegation Test&lt;/title&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css&quot;&gt;
    &lt;style&gt;
        #resizable { width: 150px; height: 150px; padding: 0.5em; }
        #resizable h3 { text-align: center; margin: 0; }
    &lt;/style&gt;

    &lt;script src=&quot;//code.jquery.com/jquery-3.6.0.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;//code.jquery.com/ui/1.13.1/jquery-ui.js&quot;&gt;&lt;/script&gt;
    &lt;script&gt;
        jQuery(document).ready( function($) {
            $( function() {
                $( &quot;.resizable&quot; ).resizable();// &lt;--- How to add a delegated event on this?
            } );

            $( &quot;button&quot; ).click( function () {
                $( &quot;#size-region&quot; ).append(&#39;&lt;div id=&quot;2&quot; style=&quot;width:150px; height: 100px;&quot; class=&quot;ui-widget-content resizable&quot;&gt;&lt;h3 class=&quot;ui-widget-header&quot;&gt;Not Resizable&lt;/h3&gt;&lt;/div&gt;&#39;);
            } );
        } );
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id=&quot;size-region&quot; class=&quot;height: 90%; width: 100%;&quot;&gt;
        &lt;div id=&quot;1&quot; style=&quot;width:150px; height: 100px;&quot; class=&quot;ui-widget-content resizable&quot;&gt;
            &lt;h3 class=&quot;ui-widget-header&quot;&gt;Resizable&lt;/h3&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;button&gt;Click me&lt;/button&gt;
&lt;/body&gt;
&lt;/html&gt;

Docs for jQuery Resizable are at https://jqueryui.com/resizable/

Info on event delegation is found at https://learn.jquery.com/events/event-delegation/

I mention the problem being larger, I believe i could just add the element with javascript for it but what if i have 10 other events to add? I'm specifically looking for a method where I can add a single js file and use this whatever is added to the size-region (if this is in fact possible)

答案1

得分: 1

考虑以下内容。

jQuery(function($) {
  function makeResize(target) {
    return $(target).resizable();
  }

  makeResize(".resizable");

  $("button").click(function() {
    var c = ($(".resizable").length + 1)
    var newBox = $("<div>", {
      id: "resize-" + c,
      class: "ui-widget-content resizable"
    }).css({
      width: "150px",
      height: "100px"
    }).appendTo("#size-region");
    $("<h3>", {
      class: "ui-widget-header"
    }).html("Resize " + c).appendTo(newBox);
    makeResize(newBox);
  });
});
#resizable {
  width: 150px;
  height: 150px;
  padding: 0.5em;
}

#resizable h3 {
  text-align: center;
  margin: 0;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css">
<script src="//code.jquery.com/jquery-3.6.0.js"></script>
<script src="//code.jquery.com/ui/1.13.1/jquery-ui.js"></script>

<div id="size-region" class="height: 90%; width: 100%;">
  <div id="resize-1" style="width:150px; height: 100px;" class="ui-widget-content resizable">
    <h3 class="ui-widget-header">Resize 1</h3>
  </div>
</div>
<button>Click me</button>

初始化jQuery UI Widget的过程无法像事件一样委托。如果您想要使用相同参数初始化大量元素,可以使用一个函数来实现。

看看makeResize()函数,我传入一个变量target,然后将其包装为jQuery对象,然后初始化Resizable。这种技术非常灵活,因为您可以传入一个字符串、一个元素或一个对象,都可以正常工作。

示例:

$("button").click(function(){
  makeResize(this);
});

使被点击的按钮可以调整大小。

$(document).on("click", "button", function(){
  makeResize(this);
});

将点击事件委托给可能创建的任何按钮,并使其可以调整大小。

我使用了更多纯粹的jQuery,这是我的选择,这并不意味着您的代码,追加HTML字符串的方法,在任何方面都是错误的。这是两种不同的方法。我更喜欢我的方法,因为它更容易阅读,更容易操作或进行小的更改/修复,也更容易使其更具动态性。

您的原始代码也可以以类似的方式工作:

$("button").click(function() {
  $("#size-region").append('<div id="2" style="width:150px; height: 100px;" class="ui-widget-content resizable"><h3 class="ui-widget-header">Not Resizable</h3></div>');
  makeResize("#2");
});

由于新的HTML字符串已经添加到DOM并被渲染,我们可以通过选择器"#2"来调用它。

这里的问题是,如果您多次单击按钮,那么现在会有多个具有相同ID的元素,而它们需要是唯一的。

最后,您不需要将jQuery包装在超过一个Ready或匿名函数中。您确实希望在执行jQuery之前让所有HTML加载并准备好。这就是$(document).ready(function(){});$(function(){});为您做的事情。

英文:

Consider the following.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

jQuery(function($) {
  function makeResize(target) {
    return $(target).resizable();
  }

  makeResize(&quot;.resizable&quot;);

  $(&quot;button&quot;).click(function() {
    var c = ($(&quot;.resizable&quot;).length + 1)
    var newBox = $(&quot;&lt;div&gt;&quot;, {
      id: &quot;resize-&quot; + c,
      class: &quot;ui-widget-content resizable&quot;
    }).css({
      width: &quot;150px&quot;,
      height: &quot;100px&quot;
    }).appendTo(&quot;#size-region&quot;);
    $(&quot;&lt;h3&gt;&quot;, {
      class: &quot;ui-widget-header&quot;
    }).html(&quot;Resize &quot; + c).appendTo(newBox);
    makeResize(newBox);
  });
});

<!-- language: lang-css -->

#resizable {
  width: 150px;
  height: 150px;
  padding: 0.5em;
}

#resizable h3 {
  text-align: center;
  margin: 0;
}

<!-- language: lang-html -->

&lt;link rel=&quot;stylesheet&quot; href=&quot;//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css&quot;&gt;
&lt;script src=&quot;//code.jquery.com/jquery-3.6.0.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;//code.jquery.com/ui/1.13.1/jquery-ui.js&quot;&gt;&lt;/script&gt;

&lt;div id=&quot;size-region&quot; class=&quot;height: 90%; width: 100%;&quot;&gt;
  &lt;div id=&quot;resize-1&quot; style=&quot;width:150px; height: 100px;&quot; class=&quot;ui-widget-content resizable&quot;&gt;
    &lt;h3 class=&quot;ui-widget-header&quot;&gt;Resize 1&lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;button&gt;Click me&lt;/button&gt;

<!-- end snippet -->

The initialization of a jQuery UI Widget cannot be delegated in the same way an Event can be. If you want to make a large number of elements be initialized with the same parameters, you can do this with a Function.

Looking at the makeResize() function, I pass in a variable, target that I then wrap so it is a jQuery Object and then initialize Resizable. This technique is very versatile as I can pass in a String, a element, or an object and it will work.

Examples:

$(&quot;button&quot;).click(function(){
  makeResize(this);
});

Makes the button that was clicked upon resizable.

$(document).on(&quot;click&quot;, &quot;button&quot;, function(){
  makeResize(this);
});

Delegate the click event to any button that might be created and make it resizable.

I used more pure jQuery and this was my choice and it does not mean that your code, appending an HTML string, is wrong in any way. Two different approaches. I prefer my method as it is easier to read down the line, easier to manipulate or make small changes/fixes, and is easier to make more dynamic.

Your original code could work in a similar way:

$(&quot;button&quot;).click(function() {
  $(&quot;#size-region&quot;).append(&#39;&lt;div id=&quot;2&quot; style=&quot;width:150px; height: 100px;&quot; class=&quot;ui-widget-content resizable&quot;&gt;&lt;h3 class=&quot;ui-widget-header&quot;&gt;Not Resizable&lt;/h3&gt;&lt;/div&gt;&#39;);
  makeResize(&quot;#2&quot;);
});

As the new HTML String has been added to the DOM, and is Rendered, we can call it by a selector, &quot;#2&quot;.

The pitfall here is that if you click the button a 2nd or 3rd time, you now have multiple elements with the same ID when they need to be unique.

Last note, you do not need to wrap the jQuery in more than one Ready or Anonymous function. You do want to let all the HTML Load and be Ready before you execute your jQuery. This is what $(document).ready(function(){}); and $(function(){}); do for you.

huangapple
  • 本文由 发表于 2023年2月8日 23:18:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387899.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定