在模板文字中插入 jQuery 元素的有效方法

Efficient method of inserting jQuery elements within template literals

涉足 jQuery,我发现自己经常 运行 陷入尴尬境地。假设我想构建一大块 HTML,中间某处有一个 jQuery-wrapped 元素。我希望能够使用模板文字来执行 HTML,然后有效地将 jQuery 包裹的元素放入其中,以避免编写大量 JavaScript 代码来单独构建每个元素在树上。

比如我想在描述的位置插入一个按钮:

const $btn = $(`<button>Click Me</button>`).click(() => { /* complex handler... */ });
const $ele = $(`<div><h1>Some content</h1><p>Press this button: [button should go here]</p></div>`);

我可以费力地创建外部 divp,将 p 附加到 div,并将 button 附加到 p。这感觉像是很多笨重的样板文件。

我可以直接将 button 添加到模板文字中:

<div><h1>Some content</h1><p>Press this button: <button>Click Me</button></p></div>

然后 find() 它并以这种方式绑定处理程序——这似乎好一点,但我仍然必须给我的 button 一个独特的 idclass 为了能够 find 它,取决于上下文。它也不 "chain" 好,例如上面的例子,将 find() 添加到我的 const $ele = .. 语句的末尾将导致 $ele 存储 button,而不是 div。这通常是不可取的。

那么,有更好的解决方案吗?

您可以 find() p 元素并将按钮附加到它,而不是 find() 它在字符串中,然后向其添加属性。这样就不需要像您提到的另一种情况那样需要 id

const $btn = $("<button>Click Me</button>").click(() => { /* complex handler... */ });
const $ele = $("<div><h1>Some content</h1><p>Press this button: </p></div>");
$ele.find("p").append($btn)

//This line is only for testing:
$ele.appendTo(document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

让我们来享受一下带标签的模板文字:

const $btn = jQuery(`<button>Click Me</button>`).click(e => alert("complex handler…"));
const $ele = $`<div><h1>Some content</h1><p>Press this button: ${$btn}</p></div>`;
//           ^^                                                ^^^^^^^          ^
jQuery("body").append($ele);

function $(parts, ...args) {
  const uid = Math.round(Math.random()*0xFFFF).toString(16).padStart(4, "0");
  const res = jQuery(parts.reduce((html, p, i) => {
    return html + "<slot name=x-replace-"+uid+"></slot>" + p;
  }));
  res.find("slot[name=x-replace-"+uid+"]").replaceWith(i => args[i]);
  return res;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

看来这是一个热门话题,所以,结合这里的一些想法,这是愚蠢的吗?:

$.fn.extend({
    swapIn: function (toSwap) {
        Object.entries(toSwap)
            .forEach(([k, $v]) => this.find(`[data-swap="${k}"]`).replaceWith($v));
        return this;
    }
});

const $btn1 = $(`<button>Click Me</button>`).click(() => { /* complex handler... */ });
const $btn2 = $(`<button>Don't Click Me</button>`).click(() => { /* complex handler... */ });
const $ele = $(`<div><h1>Some content</h1><p>Press this button: <div data-swap="$btn1"/> but not this button: <div data-swap="$btn2"/></p></div>`)
    .swapIn({$btn1, $btn2});

console.log($ele[0].innerHTML); // the desired resut, while keeping the jQuery objects handy for further manipulation

满足以下要求:

  • 易于use/minimal样板
  • Easy-ish阅读(个人认为)--可以阅读top-to-bottom
  • 连锁友好
  • 保持 jQuery objects
  • 允许任何不需要的东西jQuery-accessible(文本,headers,等等)成为模板文字的一部分