在document.ready()上选择:target [英] Selecting :target on document.ready()

查看:41
本文介绍了在document.ready()上选择:target的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是一个简单的测试用例,以演示我正在尝试做的事情:

 < html>< head>< title> Test</title></head><身体>< script src ="http://code.jquery.com/jquery-1.10.1.min.js"></script>< script type ="text/javascript">$ {document).ready(function(){$(:target").css('color','red');});</script>< ul>< li id ="one">一个</li>< li id ="two"> Two</li>< li id ="three">三个</li></ul></body></html> 

这个想法是当目标被定位时(例如,test.html#two)通过jQuery/Javascript对目标项目进行操作.

这可以在Firefox和IE 10中正常运行,但不能在Chrome,Opera或Safari中运行,这让我想知道这是否是某些浏览器中的错误,如果我尝试做的是某种错误,或者如果我遇到某些规范或其他规范中不够精确的部分的话.

如果我将jQuery代码更改为

  alert($(:target").length); 

很明显,Chrome,Opera和Safari在document.ready()期间找不到:target元素,但是稍后(通过控制台或附加到click事件的函数)调用相同的代码会找到这些元素./p>

:target应该何时可以被JS访问?

解决方案

此内容已发布为评论,但后来被删除,您可以尝试等待窗口加载事件:

  $(window).on('load hashchange',function(){$(':target').css('color','red');}); 

这对我来说在Chrome上产生了不同的结果,在刷新页面(F5)时有效,但在地址栏中按Enter键却无效.

我不知道是否可以使用:target 选择器在页面加载时正确处理此问题,但是您始终可以获取哈希值并将其用作选择器:

  $(window).on('load hashchange',function(){var target = window.location.hash;$(target).css('color','red');}); 

更新

我一直在对该问题进行一些研究,并进行了一些测试,我有几点见解可以分享:

首先,我们需要了解,在调用 $(':target')时,jQuery内部使用了 querySelectorAll(':target'),这意味着直接与伪类的CSS规范有关,但是为什么在 document.ready()内部不起作用?

好吧,我发现将代码包装在 setTimeout(fn,0)中实际上使选择器可用:

  $(document).ready(function(){setTimeout(function(){$(':target').css('color','red');//此工作},0);}); 

您可以阅读此答案,以获取有关添加零毫秒超时实际上有何不同的解释,但基本上它允许浏览器完成其他与JavaScript无关的任务(在这些任务中,我们会发现使实际的CSS伪类可用于查询).我相信Firefox以某种方式对内部流程进行不同的管理,这就是为什么代码在那里无需超时即可工作的原因.

现在,我还发现jQuery的内部sizzle选择器引擎为不支持CSS :target 伪类的浏览器提供了后备功能,您可以在 document.ready()没问题:

  $(document).ready(function(){$(':target()').css('color','red');}); 

之所以可行,是因为它不是依赖CSS类,而是一个JavaScript实现,它利用window.location对象上的hash属性,在内部对其进行了如下定义:

 "target":function(elem){var hash = window.location&&window.location.hash;返回哈希&&hash.slice(1)=== elem.id;} 

您唯一需要注意的是,如果未传递:target(div)之类的选择器,则此函数将遍历页面上的每个元素,因此我相信使用我之前提供的解决方法还是比这更好的选择.

The following is a simple test case to demonstrate what I'm trying to do:

<html>
<head>
<title>Test</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
    $(":target").css('color', 'red');
});
</script>
<ul>
    <li id="one">One</li>
    <li id="two">Two</li>
    <li id="three">Three</li>
</ul>
</body>
</html>

The idea is to do something through jQuery/Javascript to the targetted item, when something is targetted (for example, test.html#two).

This works as I expect it to in Firefox and IE 10, but not in Chrome, Opera or Safari, which leaves me wondering if this is a bug in some browsers, if what I'm trying to do is somehow wrong, or if I've run afoul of an inadequately precise part of some specification or other.

If I change the jQuery code to do

alert($(":target").length);

it becomes apparent that Chrome, Opera and Safari can't find the :target element during document.ready(), but calling the same code later (via console or function attached to a click event) does find the elements.

When should :target become accessible to JS?

解决方案

This was posted as a comment but was later removed, you can try waiting for the window load event:

$(window).on('load hashchange', function(){
    $(':target').css('color', 'red');
});

This for me produced mixed results on Chrome, it worked when doing a page refresh (F5) but not when hitting enter in the address bar.

I don't know if there's any way to handle this correctly on page load using the :target selector but you could always get the hash value and use it as your selector:

$(window).on('load hashchange', function(){
    var target = window.location.hash;
    $(target).css('color', 'red');
});

UPDATE

I've been doing some research on the issue plus some tests and I have a couple of insights to share:

First off, we need to understand that when calling $(':target') jQuery internally makes use of querySelectorAll(':target') which means it's directly related to the CSS specification of the pseudo-class, but why isn't working inside document.ready()?

Well, I found that wrapping the code inside setTimeout(fn,0) actually makes the selector available:

$(document).ready(function(){
    setTimeout(function(){
        $(':target').css('color', 'red'); //THIS WORKS
    },0);
});

You can read this answer for an explanation on how adding a zero-ms timeout actually makes a difference, but basically it allows the browser to complete other non-javascript related tasks (in which we would find making the actual CSS pseudo-class available for query). I believe Firefox somehow manages its internal processes differently and that's why the code works there without the need for a timeout.

Now I also discovered that jQuery's internal sizzle selector engine provides a fallback for browsers that do not support CSS :target pseudo-class, which you can use inside document.ready() without issue:

$(document).ready(function(){
    $(':target()').css('color', 'red');
});

This works because instead of relying on the CSS class it is a javascript implementation that makes use of the hash property on the window.location object, internally it is defined as follows:

"target": function( elem ) {
        var hash = window.location && window.location.hash;
        return hash && hash.slice( 1 ) === elem.id;
    }

The only think you should note is that this function will go through every element on the page if it's not passed a selector like :target(div), so I believe using the workaround I provided earlier would still be a better option than this.

这篇关于在document.ready()上选择:target的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆