【问题标题】:How to create shorthand for anyElement.querySelector method如何为 anyElement.querySelector 方法创建简写
【发布时间】:2021-12-17 10:08:33
【问题描述】:

可以使用以下方法为document.querySelector 创建速记

const $ = document.querySelector.bind(document);
const $$ = document.querySelectorAll.bind(document);

所以现在let a = $('a')let a = document.querySelector('a') 是等价的。

有没有办法为querySelector 方法本身创建简写?
IE。使let a = element.shortHand(args)let a = element.querySelector(args) 等同于任何(预先未知)element

编辑:由于人们说这样做是个坏主意,所以还有另一个问题:如何制作$ $$ 选择器,就像Chrome DevTools 中的选择器一样,它接受根元素作为第二个参数?
IE。使let a = $('a',element)let a = element.querySelector('a') 等价。

【问题讨论】:

  • 当然:在Element.prototype.querySelector 旁边创建一个方法。绝对不推荐。
  • 顺便提一下,有些控制台已经有Web Console Helpers,比如$$$,它们接受两个参数:选择器和根元素。
  • 您可以通过const $ = (selector, root = document) => root.querySelector(selector); 创建自己的$。很简单。
  • questions 有两个建议。我不知道为什么.bind 方法更受欢迎,但在大多数情况下,它们的工作方式应该相同。我相信,如果document 被重新定义,那么.bind 方法仍然可以工作,而箭头函数将从新的document 对象中读取querySelector,它可能没有该方法;箭头函数也需要每次都解析document,但这是一个很小的优化......并且重新定义document(在全局范围内)只能在ES6模块中进行,无论如何都不应该“随机”发生。跨度>

标签: javascript metaprogramming


【解决方案1】:

这里有一些选项:

向 Element.prototype 添加方法

Element.prototype.shortHand = Element.prototype.querySelector

这个“猴子补丁”在 DOM 本身中的 Element 类,并将这个函数添加到 DOM 中的所有元素上,这只是 querySelector 函数的副本。

非常不鼓励。这对性能不利,并且万一浏览器决定在未来添加更多与您的功能冲突的功能,这也很糟糕。但是,如果您只是在玩游戏而不发布此代码,那应该没问题。

迷你 jQuery

​​>

如果你想创建自己的迷你 jQuery,你也可以这样做:

class MiniJQuery {
  constructor(el) {
    this.el = el;
  }
  shortHand(...query) {
    return this.el.querySelector(...query);
  }
  // ... put any other functions you want to use
}
const $ = (queryOrElement) => {
  if (typeof queryOrElement === 'string') {
    return document.querySelector(queryOrElement);
  }
  return new MiniJQuery(queryOrElement);
}

// Now you can:
const a = $(element).shortHand(args);
// which is equivalent to
const a = element.querySelector(args);

这是一种更安全且没有问题的方法。我认为这不会增加太多价值,因为您只需键入稍长的方法名称,但您可以在您的类中添加更多有趣的方法以使其有价值。

代理

与上面的方法非常相似,但是您可以使用Proxy 而不是MinijQuery 类将未知方法“转发”到元素本身。这意味着$(element) 将拥有element 本身拥有的所有方法。

例子:


const handler = {
  get: function (target, prop, receiver) {
    if (prop === "shortHand") {
      return target.querySelector.bind(target);
    }
    const retVal = Reflect.get(...arguments);
    
    // Bind methods to the element.
    return typeof retVal === 'function'
      ? retVal.bind(target)
      : retVal;
  },
};

const $ = (queryOrElement) => {
  if (typeof queryOrElement === 'string') {
    return document.querySelector(queryOrElement);
  }
  // You can add all sorts of custom function handlers here.
  return new Proxy(queryOrElement, handler);
}

$('div') // gets divs
$(element).shortHand(...)
// works the same as element.querySelector
// But the HTMLElement methods still work too:
$(element).querySelector
$(element).querySelectorAll
$(element).className
// ...

在此处阅读更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

【讨论】:

  • 谢谢。您介意回答引起的附加问题吗?使 let a = $('a', element) 和 let a = element.querySelector('a') 等价。 SebastianSimon 在 cmets 中已经回答了这个问题,但我想确定一下,因为互联网文章中的每个人都显示“$ = document.querySelector.bind(document)”作为解决方案,并且没有人告诉使用简单的“$ = selector = > document.querySelector(选择器)"
  • 所以您询问的是代理解决方案。更新我原来的答案。
  • 我不太了解代理解决方案。如何使用这样的代理?如果 $('a',element) 只接受一个参数,那么 $('a',element) 应该如何工作? element.shortHand('a') 似乎也不起作用。附:问题的第二部分现在在我原始帖子的“编辑:”部分中得到了充分解释。
  • 我的错,我在编写代码示例时犯了一个错误。现在更新它是正确的。
  • .bind 是对的。我肯定错过了。你也是对的,在我的示例代码中 $(selector).shortHand 不存在。我不认为这个问题是专门寻找的,我正在尝试更容易理解的代码,而不是提供一个完整的工作解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
相关资源
最近更新 更多