【问题标题】:Can't use methods with jQuery variables不能使用带有 jQ​​uery 变量的方法
【发布时间】:2019-02-09 20:02:27
【问题描述】:

我在弄清楚我的代码为什么不起作用时遇到了一些麻烦。在下面的示例 html 中,我有三个 nav-tab 元素。我正在尝试针对第二个元素(产品选项卡)进行以下更改:

  1. 在悬停时为 div.nav-tab 元素添加红色边框(仅限产品标签)
  2. 将“产品”的文本更改为“商品”

我知道这可以通过更改 CSS 和 HTML 轻松完成,但我正在尝试仅使用 jQuery。

在我的脚本中,我试图创建一个 jQuery 变量,然后在其上使用 .hover 和 .find 方法,但我总是收到错误“.find -or- .hover is not a function”。

另外,我以后可能想在导航栏的开头添加更多选项卡,所以我不想使用类选择器之类的东西并定位第二个元素,因为当我稍后添加更多选项卡时,这最终不会定位到产品标签。比如……

$( ".nav-tab" )[1].hover...

我确信有一种简单的方法可以做到这一点。有人可以就如何最好地使用 jQuery 进行更改提供一些建议吗?提前致谢!

我创建了一个示例fiddle

<nav>
    <div class="nav-tab">
        <a class="nav-link" data-name="About">
            <div class="item-menu">
                <span>About</span>
            </div>
        </a>
    </div>
    <div class="nav-tab">
        <a class="nav-link" data-name="Products">
            <div class="item-menu">
                <span>Products</span>
            </div>
        </a>
    </div>
    <div class="nav-tab">
        <a class="nav-link" data-name="Contact">
            <div class="item-menu">
                <span>Contact</span>
            </div>
        </a>
    </div>
</nav>

<script>
$( document ).ready(function() {
    let products = $( ".nav-tab" ).has( '[data-name="Products"]' ).get( 0 );
    products.hover(
        function() {$(this).addClass("red-border")},
        function() {$(this).removeClass("red-border")}
    );
    products.find('span').innerText="Merchandise";
});
</script>

【问题讨论】:

  • 这是你想要的吗? jsfiddle.net/kLev24gy
  • 当您使用.get(0) 时,您将取消引用 jQuery 对象,从而将其更改为纯 JavaScript 对象。两个对象都不能被对方的方法“看到”。

标签: jquery


【解决方案1】:

Dereferencing jQuery Objects

当您使用 ....get(0)(或 ...[0])时,您将取消引用 jQuery 对象,从而将其更改为纯 JavaScript 对象。任何一个对象都不能被对方的方法“看到”。不要使用.get(0),通常只在一个变量中存储一个jQuery对象就足够了。

IMO .hover() 方法有问题,很容易被 CSS 伪类 :hover 替换。作为 jQuery 解决方案,带有 mouseentermouseleave 事件的 .on() 方法更好,以便您可以单独处理每个事件。 .innerText 是一个纯 JavaScript 属性,无法识别 jQuery 对象,请改用 jQuery 方法 .text()

另外,不要使用 CSS border 属性,而是使用 outlineoutline 不会增加它的长度,而border 会因此导致相邻元素移动。


演示

demo中有详细的评论。

$(document).ready(function() {
  // Reference as a jQuery Object
  const products = $('[data-name="Products"]');
  // Register both events on element...
  products.on('mouseenter mouseleave', function(event) {
    // if the type of event is 'mouseenter...
    if (event.type === 'mouseenter') {
      // Get it's descendant <span>, change it's text, then add .red-border to it
      $(this).find('span').text("Merchandise").addClass("red-border");
      // Otherwise do the opposite
    } else {
      $(this).find('span').text("Product").removeClass("red-border");
    }
  });
});
.red-border {
  outline: 3px dashed red
}
<nav>
  <div class="nav-tab">
    <a class="nav-link" data-name="About">
      <div class="item-menu">
        <span>About</span>
      </div>
    </a>
  </div>
  <div class="nav-tab">
    <a class="nav-link" data-name="Products">
      <div class="item-menu">
        <span>Products</span>
      </div>
    </a>
  </div>
  <div class="nav-tab">
    <a class="nav-link" data-name="Contact">
      <div class="item-menu">
        <span>Contact</span>
      </div>
    </a>
  </div>
</nav>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

【讨论】:

    【解决方案2】:

    当您使用 $(".nav-tab")[1] 时,您正在转义对象周围的 jQuery 包装器,这就是为什么它不允许使用 jQuery 相关项目,未经测试但是您可以尝试通过像 $($(".nav-tab")[1]).hover() 再次包装它来修复它,但这不是您应该这样做的方式。

    最好的方法是结合使用 CSS 选择器和 jQuery 的 .parent() 函数,如下所示:

    let products = $("[data-name='Products']").parent();
    

    这样,您只需选择上面找到的元素的第一个父元素。

    也可以在上面添加一个特定的选择器来使它像这样(虽然不是必需的):

    let products = $("[data-name='Products']").parent(".nav-tab");
    

    https://api.jquery.com/parent/

    而对于文本更改,只需使用 jQuery 的 .text() 函数:

    products.find("span").text("Merchandise");
    

    https://api.jquery.com/text/

    也可以查看此方法以选择许多中的第一个对象 jQueryhttps://api.jquery.com/first/

    编辑:由于您获得的是第二个对象,因此上述 .first() 不相关, .get() 是您想要的,但这仍然不是您应该这样做的方式,因为正如您所提到的,如果您附加另一个导航选项卡,那么它将破坏一切。

    【讨论】:

      【解决方案3】:

      使用此代码:

      $( document ).ready(function() {
          var products = $( ".nav-tab").find("[data-name='Products']");
        products
        .mouseover(function(){
          $(this).find("span").text("Merchandise").closest(".nav-tab").addClass("red-border");
        })
        .mouseout(function(){
          $(this).parent(".nav-tab").removeClass("red-border");
          //Again if you want to replace "Merchandise" to "Product" then active this commanded line
          //$(this).closest(".nav-tab").removeClass("red-border").find("span").text("Products");
        });
      });
      

      我在 fiddler 中更新了你的代码:https://jsfiddle.net/Arif2009/gksoynLq/31/

      【讨论】:

        【解决方案4】:

        试试这个:

        $( document ).ready(function() {
        var products =  $(".nav-tab a[data-name=Products]");
          $(products).hover(function(){
            $(this).addClass('red-border');
            }, function(){
            $(this).removeClass('red-border');
          });
          $('span',products)[0].innerText="Merchandise";
        });
        

        【讨论】:

        • 纯代码答案没有用。你做了什么?为什么它有效?考虑添加一些 cmets / 描述 / 解释你做了什么以及为什么。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-25
        相关资源
        最近更新 更多